pykka Documentation

repository·main·Indexed 23 days ago

https://github.com/jodal/pykka

Pykka is a Python implementation of the actor model designed to facilitate the development of concurrent applications. It provides tools for isolating state and managing communication between execution units via message-passing using ThreadingActor, ActorRef, and ActorProxy. The library includes features for asynchronous and synchronous-style access through futures, worker pool patterns with pykka.get_all(), and debugging utilities like log_thread_tracebacks() for resolving deadlocks.

Tokens
9.2K
Snippets
17
Records
61
Agent score
78%

What's inside pykka

  1. What is Pykka?

    main
    Pykka is a Python implementation of the actor model. It provides a set of rules to control state sharing and cooperation between execution units, making it easier to build concurrent applications by managing how different parts of a program interact without traditional shared-state concurrency issues.
  2. What is Pykka and the Actor Model?

    main
    Pykka is a Python implementation of the actor model. The actor model provides a set of rules for controlling state sharing and cooperation between execution units, which simplifies the development of concurrent applications by reducing the complexities typically associated with shared state.
  3. General approach for testing actors

    main

    To test actors in a setting as close to production as possible, follow this lifecycle pattern:

    1. Setup: Start the actor under test along with any required collaborators or dependencies. Use mocks to replace dependencies to control their behavior.
    2. Execution: Use ask() or tell() to send messages to the actor.
    3. Assertion: Assert against the actor's internal state or the return value received from the ask() call.
    4. Teardown: Stop the actor to ensure proper cleanup before the next test runs.
  4. Understand the Actor Model in Pykka

    main
    Pykka implements the actor model, a concurrency pattern where 'actors' serve as the fundamental building blocks of computation. Instead of using shared memory and locks, actors communicate exclusively through message-passing. This approach simplifies concurrent application development by isolating state within individual execution units.
  5. Create a basic message-processing actor

    main

    A Pykka actor is a class that implements the on_receive(message) method. To create one, inherit from a base actor class like pykka.ThreadingActor. The on_receive method is called whenever the actor receives a message.

    import pykka
    
    class Greeter(pykka.ThreadingActor):
        def on_receive(self, message):
            print("Hi there!")
  6. Understand Pykka log levels

    main

    Pykka uses different log levels to categorize messages. You can filter these to control the verbosity of the library's output:

    • logging.CRITICAL: Used only by debug helpers in pykka.debug.
    • logging.ERROR: Exceptions raised by an actor that are not captured into a reply future.
    • logging.WARNING: Unhandled messages and other potential programming errors.
    • logging.INFO: Exceptions raised by an actor that are captured into a reply future. During development, it is recommended to keep this level enabled to catch bugs early.
    • logging.DEBUG: Logs actor lifecycle events (starting, stopping, registering, or unregistering in the registry).
  7. Reply to messages and handle exceptions

    main

    When using ask(), an actor replies to the sender by returning a value from its on_receive(message) method. If the method returns nothing or explicitly returns None, the sender receives None.

    If an exception is raised inside on_receive() while using ask(), that exception will propagate to the sender.

    import pykka
    
    # Replying to a message
    class Greeter(pykka.ThreadingActor):
        def on_receive(self, message):
            return "Hi there!"
    
    actor_ref = Greeter.start()
    answer = actor_ref.ask("Hi?")
    print(answer) # => "Hi there!"
    
    # Propagating an exception
    class Raiser(pykka.ThreadingActor):
        def on_receive(self, message):
            raise Exception("Oops")
    
    actor_ref = Raiser.start()
    try:
        actor_ref.ask("How are you?")
    except Exception as e:
        print(repr(e)) # => Exception("Oops")
  8. Use the Threading runtime

    main

    The threading runtime is the default execution model for Pykka and requires no external dependencies beyond Pykka and the Python standard library. It provides the following core classes for actor-based concurrency:

    • pykka.ThreadingActor: The base class for creating actors that run in their own threads.
    • pykka.ThreadingFuture: A future implementation used to retrieve results from asynchronous calls within the threading runtime.
  9. Understand Pykka's concurrency runtimes

    main

    Pykka uses a single concurrency runtime model; it does not support mixing different runtimes within a single application.

    By default, Pykka uses Python's standard threading module. While older versions (Pykka 2 and earlier) supported gevent or eventlet, these alternative implementations were removed in Pykka 3. Therefore, all modern Pykka usage relies on the threading model.

  10. Use actor proxies to mirror an actor's API

    main

    An actor proxy is an abstraction that provides a convenient way to interact with an actor. The proxy uses introspection to mirror the actor's public API (methods and attributes). Any attribute or method prefixed with an underscore (_) is ignored, following Python's private member convention.

    To use a proxy, first start an actor to get an ActorRef, then call .proxy() on that reference.

    import pykka
    
    class Calculator(pykka.ThreadingActor):
        def __init__(self):
            super().__init__()
            self.last_result = None
    
        def add(self, a, b=None):
            if b is not None:
                self.last_result = a + b
            else:
                self.last_result += a
            return self.last_result
    
    actor_ref = Calculator.start()
    proxy = actor_ref.proxy()
  11. How cooperating actors work in Pykka

    main

    In Pykka, actors can cooperate by interacting with one another through ActorRef or ActorProxy instances. This interaction can be established in two ways:

    1. At setup time: Pass the ActorRef or ActorProxy as arguments to the actor's start() method.
    2. During runtime: Pass the references later via messages sent to the actor.

    By passing these references, one actor can invoke methods on another (via a proxy) or send messages to another (via a reference), enabling complex multi-actor workflows.

  12. Core rules of Pykka actors

    main

    To build reliable concurrent applications with Pykka, you must adhere to the following actor model principles:

    • Isolation: An actor is an independent execution unit. It maintains its own private state and does not share it with any other actor.
    • Communication: Actors interact solely by sending and receiving messages. An actor can only communicate with others if it possesses their address.
    • Message Processing: An actor processes exactly one message at a time. Because of this sequential processing within a single actor, you do not need to use internal locks to protect an actor's own state.
    • Reactive Actions: Upon receiving a message, an actor can:
      • Alter its own internal state.
      • Send messages to other known actors.
      • Start new actors.

    These actions are optional and can be performed in any order.