Skip to main content

repod — Networking library for multiplayer games in Python

Python 3.12+ License: LGPL v3 Ruff msgpack asyncio

repod is a networking library designed to make it easy to write multiplayer games in Python. It uses asyncio and msgpack to asynchronously serialize network events and arbitrary data structures, and delivers them to your high-level classes through simple callback methods.

It is a modernized fork of PodSixNet. Same ideas -- channels, action-based message dispatch, synchronous pump loops -- but rebuilt from scratch for Python 3.12+ with async I/O, binary msgpack serialization, and full type annotations. PodSixNet was built on asyncore, which was removed in Python 3.12; repod is the drop-in replacement.

Each class within your game client which wants to receive network events subclasses ConnectionListener and implements Network_* methods to catch specific events from the server. You don't have to wait for buffers to fill, or check sockets for waiting data or anything like that -- just call client.pump() once per game loop and the library handles everything else, passing off events to your listener. Sending data back to the server is just as easy with client.send(mydata). On the server side, events are propagated to Network_* callbacks on your Channel subclass, and data is sent back to clients with channel.send(mydata).

Install

pip install repodnet

Or with uv:

uv add repodnet

Examples

Each example lives in its own folder under examples/ with a server.py and client.py.

Chat:

  • python examples/chat/server.py
  • python examples/chat/client.py

Whiteboard (requires pygame-ce):

  • python examples/whiteboard/server.py
  • python examples/whiteboard/client.py

Tag game (requires raylib):

  • python examples/tag/server.py
  • python examples/tag/client.py

Latency measurement:

  • python examples/lag_time/server.py
  • python examples/lag_time/client.py

Quick start -- Server

You need to subclass two classes to make your own server. Each time a client connects, a new Channel instance is created, so you subclass Channel to make your server-side representation of a client:

from repod import Channel

class ClientChannel(Channel):

    def network_received(self, data: dict) -> None:
        print(data)

    def Network_myaction(self, data: dict) -> None:
        print("myaction:", data)

Whenever the client sends data, the network_received() fallback is called if no specific handler exists. The method Network_myaction() is only called if your data has an "action" key with a value of "myaction". In other words, if the data looks like:

{"action": "myaction", "blah": 123, ...}

Next, subclass Server:

from repod import Server

class MyServer(Server):
    channel_class = ClientChannel

    def on_connect(self, channel, addr):
        print("new connection:", channel)

Set channel_class to the Channel subclass you created above. The on_connect() method is called whenever a new client connects.

To run the server, call launch():

MyServer(host="0.0.0.0", port=5071).launch()

That's it. One line. launch() handles the event loop internally and catches Ctrl+C for clean shutdown.

When you want to send data to a specific client, use the send method on the Channel:

channel.send({"action": "hello", "message": "hello client!"})

Quick start -- Client

To connect to your server, subclass ConnectionListener:

import time
from repod import ConnectionListener

class MyClient(ConnectionListener):

    def Network_connected(self, data: dict) -> None:
        print("connected to the server")

    def Network_error(self, data: dict) -> None:
        print("error:", data["error"])

    def Network_disconnected(self, data: dict) -> None:
        print("disconnected from the server")

    def Network_myaction(self, data: dict) -> None:
        print("myaction:", data)

Network events are received by Network_* callback methods. Replace * with the value of the "action" key you want to catch. The connected, disconnected, and error events are sent automatically by repod.

Connect and pump:

client = MyClient()
client.connect("localhost", 5071)

while True:
    client.pump()
    time.sleep(0.01)

Call pump() once per game loop and repod handles everything -- reading from the socket, deserializing, and dispatching to your Network_* methods. Sending data to the server:

client.send({"action": "myaction", "blah": 123, "things": [3, 4, 3, 4, 7]})

This works with any game framework that has a main loop: pygame, raylib, arcade, pyglet, etc. Just drop pump() into the loop.

Documentation

Full tutorial and API reference: walkercito.github.io/repod

Why not PodSixNet?

PodSixNet was great for its time, but:

  • It's built on asyncore, which was removed in Python 3.12
  • It uses rencode / custom delimiter-based framing (\0---\0), which is fragile with binary data
  • It has no type annotations, no modern tooling support
  • It is no longer maintained (chr15m/PodSixNet#46)

repod keeps the same simple API philosophy but replaces the internals:

  • asyncio instead of asyncore
  • msgpack with length-prefix framing instead of rencode with delimiter framing
  • Full type annotations with PEP 695 generics (optional)
  • Python 3.12+ only -- no compatibility shims

Development

uv sync --dev
uv run ruff check .
uv run ruff format --check .
uv run ty check
uv run pytest tests/ -v

License

Copyright Walkercito, 2026.

repod is licensed under the terms of the LGPL v3.0 or later. See the COPYING file for details.

This is the same license as PodSixNet, from which repod is forked. In short: you can use repod in any project (commercial or otherwise), but if you modify the repod library code itself, you must make the modified source available.

Metadata

Release files for repodnet 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for repodnet 0.1.2
File Size Uploaded Provenance Actions
repodnet-0.1.2.tar.gz 76.6 kB Without provenance Details for repodnet-0.1.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for repodnet 0.1.2
File Interpreter ABI Platform Actions
repodnet-0.1.2-py3-none-any.whl Python 3 none any Details for repodnet-0.1.2-py3-none-any.whl

Total release size: 96.4 kB

Release files / repodnet-0.1.2.tar.gz

Download URL repodnet-0.1.2.tar.gz
Size 76.6 kB
Tags Source
SHA-256 checksum
How to use checksums
e533f28e0b2ff732025ff86bfe3009648bca0630ae3d7bea069645c2cbbda820
BLAKE2b-256 checksum
How to use checksums
49535f758d82417193098d0b2e3d84092484f975c9cd1b1698c1e173c91d687e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.10.8 {"installer":{"name":"uv","version":"0.10.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / repodnet-0.1.2-py3-none-any.whl

Download URL repodnet-0.1.2-py3-none-any.whl
Size 19.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0709dbf529541d1d6700815394fef55352793b95dc930ef739616cdad03ab15a
BLAKE2b-256 checksum
How to use checksums
1a072c0825d3ffb3649c54bbfa3a4e4dc9d2f174a45ba732cd95b5d8e014ebd0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.10.8 {"installer":{"name":"uv","version":"0.10.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for repodnet 0.1.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page