Pyro5 Remote Object Communication Library

5.16 · maintenance · verified Thu Apr 16

Pyro5 is a Python library for remote object communication, enabling client-server interactions across different processes or machines. It's the fifth major version of the Pyro project, emphasizing ease of use and flexibility. As of version 5.16, the project has entered a low maintenance mode, with active development paused unless critical bugs are reported.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates a basic Pyro5 client-server interaction. It defines a server class, registers it with a Pyro Name Server, and then a client looks up the server and calls its methods. Before running, ensure you start the Pyro Name Server in a *separate* terminal using `python -m Pyro5.nameserver`. This is crucial for name lookup. The provided code attempts to run both server and client within the same script using threads for convenience, but in typical usage, they are separate processes, potentially on different machines.

import Pyro5.api
import time
import threading

# --- Server side (run in one terminal) ---
@Pyro5.api.expose
class MyServer:
    def greet(self, name):
        return f"Hello, {name}! This is Pyro5."

    def echo(self, message):
        return f"Server received: {message}"

    def get_time(self):
        return time.time()

def run_server():
    # Start a Name Server in a separate terminal: python -m Pyro5.nameserver
    # Or, start one programmatically if not using a shared nameserver
    # For simplicity, we'll try to connect to one assumed to be running on localhost
    try:
        ns = Pyro5.api.locate_ns(host="localhost")
    except Pyro5.errors.NamingError:
        print("No Name Server found. Please start one: python -m Pyro5.nameserver")
        return

    daemon = Pyro5.api.Daemon(host="localhost")
    uri = daemon.register(MyServer, "example.myserver") # Register with a name
    ns.register("example.myserver", uri) # Register the URI with the Name Server
    print(f"Server URI: {uri}")
    print("Server ready. Object registered as 'example.myserver'.")
    print("Starting event loop (Ctrl+C to stop)...")
    daemon.requestLoop()

# --- Client side (run in another terminal) ---
def run_client():
    # Locate the Name Server to find the object
    try:
        ns = Pyro5.api.locate_ns(host="localhost")
    except Pyro5.errors.NamingError:
        print("No Name Server found. Cannot connect to server.")
        return

    uri = ns.lookup("example.myserver") # Look up the object's URI by its name

    # Create a proxy to the remote object
    with Pyro5.api.Proxy(uri) as server_proxy:
        print(f"Greeting: {server_proxy.greet('Pyro User')}")
        print(f"Echo: {server_proxy.echo('This is a test message.')}")
        print(f"Remote time: {server_proxy.get_time()}")

if __name__ == '__main__':
    # This quickstart demonstrates client-server. 
    # For actual usage, run server and client in separate processes.
    print("--- Pyro5 Quickstart ---")
    print("To run, first start the Pyro Name Server in a *separate* terminal:")
    print("  python -m Pyro5.nameserver
")
    print("Then run this script. It will run the server, wait, then the client.")
    print("Or, copy the server part to 'server.py' and client to 'client.py' and run them separately.")

    # Simplified running for quickstart; normally they are separate processes
    server_thread = threading.Thread(target=run_server)
    server_thread.daemon = True # Allow main program to exit even if server is running
    server_thread.start()

    print("\nWaiting for server to start and register...")
    time.sleep(2) # Give server a moment to start and register

    print("\n--- Running Client ---")
    run_client()
    print("\nClient finished.")
    # The server thread will continue running until Ctrl+C if it was main, 
    # but here it's a daemon thread so it will exit with main.

view raw JSON →