Registry / http-networking / pyro4
library4.82pypypi✓ verified 87d ago

Pyro4 is a robust and mature distributed object middleware for Python, enabling remote method calls (RPC) between Python applications. It reached its last major release with 4.82 in August 2020 and is now in a maintenance-only mode, with active development having shifted to its successor, Pyro5. Pyro4 offers features like name server discovery, object exposure, and various serialization options, making it suitable for creating distributed systems, but users should be aware of its end-of-life status for new feature development.

pip install Pyro4
INSTALL
IMPORT
SIG · PYRO4
P
pyro4
http-networkingpythonv4.82
Install
1.7s avg
Import
100ms
Disk
17MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v4.82 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.920 runs
installs and imports cleanly · install 0.0s · import 0.103s · 18.5MB
glibc
py 3.103.920 runs
installs and imports cleanly · install 1.7s · import 0.098s · 19MB
17MB installed
● package 17MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

Daemon
from Pyro4 import Daemon
Proxy
from Pyro4 import Proxy
expose
from Pyro4 import expose
locateNS
from Pyro4 import locateNS
URI
from Pyro4 import URI
errors
from Pyro4 import errors

This quickstart demonstrates a basic Pyro4 remote procedure call (RPC). It shows a server exposing a `GreetingMaker` object and a client connecting to it to call a remote method. For a fully distributed setup, you would typically run `pyro4-ns` (the Pyro4 Name Server) in a separate terminal, and both server and client would interact with it via `Pyro4.locateNS()` for discovery. This example simplifies by sharing the URI directly for self-contained execution.

import Pyro4 import threading import time # --- Server Code (run in a separate thread/process) --- @Pyro4.expose class GreetingMaker(object): def get_fortune(self, name): return f"Hello, {name}. This is your fortune from Pyro4!" def run_server(): # In a real scenario, you'd run 'pyro4-ns' in a separate terminal # For this example, we mock the Name Server interaction locally. # Or, you'd start the Name Server programmatically: # ns_thread = threading.Thread(target=Pyro4.naming.startNsLoop, daemon=True) # ns_thread.start() # time.sleep(1) # Give it a moment to start print("Pyro4 server starting...") daemon = Pyro4.Daemon() # We'll use a local registration for this quickstart without needing pyro4-ns to be separately run # In a real app, you'd use ns = Pyro4.locateNS() and ns.register() # For simplicity, we just register directly with the daemon and use its URI. uri = daemon.register(GreetingMaker, "example.greeting") print(f"Object registered with URI: {uri}") print("Server ready. Waiting for calls...") daemon.requestLoop() # --- Client Code --- def run_client(server_uri): print("Pyro4 client connecting...") try: # Use the URI obtained from the server directly with Pyro4.Proxy(server_uri) as greeter: print("Client got proxy.") print(greeter.get_fortune("World")) print(greeter.get_fortune("Pythonista")) except Exception as e: print(f"Client error: {e}") if __name__ == "__main__": # To make this runnable as a single script for quickstart: # 1. Run the Name Server manually in a separate terminal: pyro4-ns # 2. Then, run this script. The server will register itself. # For this quickstart, we'll demonstrate a simplified local interaction # without explicitly starting a separate Name Server process within the script. # In a real distributed setup, `pyro4-ns` is essential. # Simplified local setup: Server registers object, client connects directly to its URI daemon = Pyro4.Daemon() # start a new Pyro daemon server_uri = daemon.register(GreetingMaker, "example.greeting") # register the object print(f"Server object URI: {server_uri}") server_thread = threading.Thread(target=daemon.requestLoop, daemon=True) server_thread.start() time.sleep(0.5) # Give the server a moment to start run_client(server_uri) print("Demonstration complete.") daemon.shutdown()
pyro4 --version
Debug
Known issues
breakingPyro4 is not backward compatible with Pyro5. If migrating or starting a new project, consider using Pyro5 as it's the actively developed version. Do not mix Pyro4 and Pyro5 components.
fix
Choose either Pyro4 or Pyro5 for your entire project. For new development, prefer Pyro5. For existing Pyro4 systems, stick to Pyro4 or plan a full migration.
affects: All Pyro4 versions when interacting with Pyro5
deprecatedPyro4 is in maintenance mode; active development has shifted to Pyro5. No new features will be added to Pyro4, only critical bug fixes.
fix
For new projects, strongly consider using Pyro5. For existing Pyro4 projects, be aware that support is limited to critical issues.
affects: 4.x
gotchaBy default, Pyro4 uses its internal 'serpent' serializer, which is more restrictive than 'pickle'. If you need to pass complex custom objects or objects with unpicklable components, you might encounter serialization errors.
fix
Ensure objects passed between Pyro4 components are serializable by 'serpent' or configure Pyro4 to use a different serializer (e.g., `Pyro4.config.SERIALIZER = 'pickle'`) at the start of both server and client applications. Be aware of pickle's security implications.
affects: All 4.x
gotchaPyro4 does not provide authentication or authorization by default. Exposing Pyro objects on public networks without proper security measures is highly risky.
fix
Implement your own security layer (e.g., VPN, SSH tunnels, IP whitelisting) around Pyro4 communication, or upgrade to Pyro5 which offers more security features.
affects: All 4.x
gotchaThe Pyro Name Server (pyro4-ns) is crucial for object discovery but must be run separately. Clients and servers will fail to locate objects if the Name Server isn't running or isn't accessible.
fix
Ensure `pyro4-ns` is running and accessible (check firewall rules, IP address, and port). You can start it from the command line: `pyro4-ns -n your_ip_address` or `pyro4-ns` for localhost.
affects: All 4.x
Errors
Common errors & fixes
Pyro4.errors.NamingError: no name server found
The Pyro Name Server (`pyro4-ns`) is not running or the client/server cannot connect to it.
fix
Start the Name Server in a separate terminal: `pyro4-ns`. Ensure firewall rules allow connections on the Name Server's port (default 9090).
socket.error: [Errno 111] Connection refused
The Pyro daemon (server) is not running at the specified address and port, or a firewall is blocking the connection.
fix
Verify the server application is running. Check firewall settings on both client and server machines to allow traffic on the Pyro daemon's port. Ensure the IP address/hostname used for connection is correct.
AttributeError: 'Proxy' object has no attribute 'my_method'
The method 'my_method' on the remote object was not exposed using `@Pyro4.expose` or `Pyro4.expose()` for classes/functions, or the client is trying to call a private method.
fix
Decorate all methods intended for remote access with `@Pyro4.expose` in the server-side object definition. Ensure the method name is correct and not a private method (starting with `_` or `__`).
TypeError: cannot pickle '_thread.RLock' object
You are trying to pass an object that cannot be serialized by the current serializer (e.g., 'serpent' or 'pickle' with unpicklable components) between client and server.
fix
Either refactor the object to remove unserializable parts, or configure Pyro4 to use a more permissive serializer if appropriate (e.g., `Pyro4.config.SERIALIZER = 'pickle'`). If using pickle, ensure all parts of the object are picklable.
Upgrade
Version history
4.82latest on PyPI · released Dec 25, 2021
Audit
Dependencies

No dependency data recorded yet.

Agent activity
13 hits · last 30 days
node
10
Resources
pyro4 — pip install pyro4 · libregistry