🌀 Pykka makes it easier to build concurrent applications.

Overview

🌀 Pykka

Pykka makes it easier to build concurrent applications.

CI Docs Coverage PyPI


Pykka is a Python implementation of the actor model. The actor model introduces some simple rules to control the sharing of state and cooperation between execution units, which makes it easier to build concurrent applications.

For a quickstart guide and a complete API reference, see the documentation.

Installation

Pykka requires Python 3.7 or newer.

Pykka is available from PyPI:

python3 -m pip install pykka

Project resources

License

Pykka is copyright 2010-2021 Stein Magnus Jodal and contributors. Pykka is licensed under the Apache License, Version 2.0.

Comments
  • Base Message Class?

    Base Message Class?

    hi, first, thank you for creating such a useful package in python :) I just start to try out pykka. just a suggestion. the message pass through actors is an dict, do you think we could have a base message class to extend? I think it might be more powerful than dict.

    enhancement 
    opened by hugo-zheng 10
  • Pykka test support

    Pykka test support

    One of the main advantages of using the Actor model is its ease of testing.

    Every actor is by default isolated and so verifying the individual behaviours of Actors should be easy because we can provide each actor with fake / stub collaborators and verify that the right messages (of the appropriate formats) are sent and received.

    However, it's not simple to capture this in the form of an assertion in a unit test.

    Perhaps a couple of examples of how Pykka actors can be tested with popular test/mocking frameworks would help here.

    docs 
    opened by fatuhoku 10
  • allow futures to be awaited and yielded from

    allow futures to be awaited and yielded from

    Currently Pykka futures are not compatible with the await and yield from syntax. This PR simply adds that capability by implementing __await__ and __iter__ on the base Future class

    opened by lime-green 7
  • interaction problem between PVector from Pyrsistent and pykka under Python 3.8

    interaction problem between PVector from Pyrsistent and pykka under Python 3.8

    there seems to be a general problem in the interaction between PVector from Pyrsistent and pykka Since Python 3.8, causing recursion errors of the form:

    onsite_1    | Traceback (most recent call last):
    onsite_1    |   File "/ems/onsite/main.py", line 49, in <module>
    onsite_1    |     _cls_operator = CLSOperator.new(_cls, _notifier)
    onsite_1    |   File "/ems/cls/operator.py", line 175, in new
    onsite_1    |     actor.update_cls(pvector(ecls)).get() # sync up
    onsite_1    |   File "/opt/venv/lib/python3.8/site-packages/pykka/_threading.py", line 55, in get
    onsite_1    |     raise exc_value
    onsite_1    |   File "/opt/venv/lib/python3.8/site-packages/pykka/_actor.py", line 186, in _actor_loop
    onsite_1    |     response = self._handle_receive(envelope.message)
    onsite_1    |   File "/opt/venv/lib/python3.8/site-packages/pykka/_actor.py", line 286, in _handle_receive
    onsite_1    |     return callee(*message.args, **message.kwargs)
    onsite_1    |   File "/ems/cls/operator.py", line 78, in update_cls
    onsite_1    |     self.reset_proxies()
    onsite_1    |   File "/ems/cls/operator.py", line 95, in reset_proxies
    onsite_1    |     self.proxies = [CLSProxy.new(channel(cls)) for cls in self.cls_set]
    onsite_1    |   File "/ems/cls/operator.py", line 95, in <listcomp>
    onsite_1    |     self.proxies = [CLSProxy.new(channel(cls)) for cls in self.cls_set]
    onsite_1    |   File "/ems/cls/operator.py", line 93, in channel
    onsite_1    |     return PresentCLSStateChannel.new(_present_cls_state_channel_seal, cls, self.actor_ref.proxy())
    onsite_1    |   File "/opt/venv/lib/python3.8/site-packages/pykka/_ref.py", line 170, in proxy
    onsite_1    |     return ActorProxy(self)
    onsite_1    |   File "/opt/venv/lib/python3.8/site-packages/pykka/_proxy.py", line 124, in __init__
    onsite_1    |     self._known_attrs = self._introspect_attributes()
    onsite_1    |   File "/opt/venv/lib/python3.8/site-packages/pykka/_proxy.py", line 141, in _introspect_attributes
    onsite_1    |     if self._is_self_proxy(attr):
    onsite_1    |   File "/opt/venv/lib/python3.8/site-packages/pykka/_proxy.py", line 173, in _is_self_proxy
    onsite_1    |     return attr == self
    onsite_1    |   File "/opt/venv/lib/python3.8/site-packages/pyrsistent/_pvector.py", line 81, in __eq__
    onsite_1    |     return self is other or (hasattr(other, '__len__') and self._count == len(other)) and compare_pvector(self, other, operator.eq)
    onsite_1    |   File "/opt/venv/lib/python3.8/site-packages/pykka/_proxy.py", line 215, in __getattr__
    onsite_1    |     if attr_path not in self._known_attrs:
    onsite_1    |   File "/opt/venv/lib/python3.8/site-packages/pykka/_proxy.py", line 215, in __getattr__
    onsite_1    |     if attr_path not in self._known_attrs:
    onsite_1    |   File "/opt/venv/lib/python3.8/site-packages/pykka/_proxy.py", line 215, in __getattr__
    onsite_1    |     if attr_path not in self._known_attrs:
    onsite_1    |   [Previous line repeated 980 more times]
    onsite_1    | RecursionError: maximum recursion depth exceeded
    

    Seems like generally the problem does not occur when wrapping PVector as fields

    opened by chemouda 5
  • Pykka blocking fastapi to server other clients

    Pykka blocking fastapi to server other clients

    Hi, I have an app that resembles the snippet code like follows:

    
    from fastapi import FastAPI
    import time
    
    import pykka
    
    
    class AnActor(pykka.ThreadingActor):
        field = 'this is the value of AnActor.field'
    
        def func(self):
            time.sleep(0.5)  # Block a bit to make it realistic
            return 'this was returned by AnActor.func() after a delay'
    
    app = FastAPI()
    actor = AnActor.start().proxy()
    
    @app.get("/")
    async def do_things():
        result = await actor.func()
        return {"message": result}
    

    To my surprise that it seems that at the actor.func call the request handler blocks, instead of yielding the control back to fastapi to handle requests. I thought the await statement should achieve that and only return when the func function is done with its own business. Am I misunderstanding pykka's design goal here? Is there any way to achieve what I want to do?

    opened by bobfang1992 5
  • on_failure for proxy

    on_failure for proxy

    Hello, I have found little need to use on_receive with the great proxy feature. However I have found the following. Consider this code:

    class MyActor(pykka.ThreadingActor):
    
        def __init__(self):
            super(MyActor, self).__init__()
            self.use_daemon_thread = True
    
        def on_receive(self, message):
            self.method_not_found()
    
        def execute(self):
            self.this_method_not_found()
    
        def on_failure(self, exception_type, exception_value, traceback):
            print("**MyActor.on_failure(%s, %s, %s" %(exception_type, exception_value, traceback))
    
    actor_ref = MyActor.start()
    #actor_ref.tell({"foo" : "bar"}) # this gives desired behavior (call to on_failure)
    p = actor_ref.proxy()
    future = p.execute() # this does not call on_failure
    future.get() # raises exception
    

    The commented code (foo/bar) fails due to the method not existing and calls on_failure as desired. But the call to p.execute() does not call on_failure. This is because execute() called through the proxy returns a future and one must call get() on the future to access the exception. This seems quite appropriate for "ask" style messaging, but for "tell" style it is cumbersome. I want to "send and forget" messages. I don't want my routine to block while waiting for the message to be processed.

    Is there a better way to use proxies with a "failure handler" without blocking, or do I have to fall back on standard tell/ask/on_receive?

    Thanks.

    enhancement 
    opened by dastultz 5
  • Reverse actor stopping order (was: Check that actor is still runable after message has been recieved.)

    Reverse actor stopping order (was: Check that actor is still runable after message has been recieved.)

    On line https://github.com/jodal/pykka/blob/master/pykka/actor.py#L164 the check for the run-able state is done before inbox.get() which can block for any amount of time, during this waiting run-able can very well have changed.

    Symptom of this problem is not finding the refs that you expect in the actor registry. This happens easily when stress-testing with a lot of clients in my current mopidy branch. For each new connection a ThreadingActor is started and as socket data is received it is delivered as a message. Then I CTRL^C mopidy and it stops all the actors, however, since some of my actors have messages in their inbox still they will go on to handle them despite being stopped. Part of this handling includes looking for other non-running actors which of course fails.

    enhancement 
    opened by adamcik 5
  • AttributeError: Queue instance has no attribute 'not_full'

    AttributeError: Queue instance has no attribute 'not_full'

    Using Pykka 0.12.2-1 and Python 2.7.1-5ubuntu2.

    Exception in thread Thread-3:
    Traceback (most recent call last):
      File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
        self.run()
      File "/usr/lib/pymodules/python2.7/pykka/actor.py", line 331, in run
        return Actor._run(self)
      File "/usr/lib/pymodules/python2.7/pykka/actor.py", line 174, in _run
        message['reply_to'].set_exception(exception)
      File "/usr/lib/pymodules/python2.7/pykka/future.py", line 104, in set_exception
        self.set(exception)
      File "/usr/lib/pymodules/python2.7/pykka/future.py", line 101, in set
        self._queue.put(value)
      File "/usr/lib/python2.7/Queue.py", line 118, in put
        self.not_full.acquire()
    AttributeError: Queue instance has no attribute 'not_full'
    
    bug 
    opened by jodal 5
  • multiprocessing Actor

    multiprocessing Actor

    Hi,

    I am new to python and would like to build my app using pyakka (I have plenty of experience using akka).

    I have read about the pitfalls of threading and the GIL in pyhon and was wondering if it would make sense to create a MultiProcessingActor, as an alternative to the ThreadActor, which would bypass the single GIL bottleneck?

    Thanks Daniel

    opened by cullender-skew 4
  • How comes I can't see Pykka debug log messages?

    How comes I can't see Pykka debug log messages?

    EDIT: I've solved my problem. I thought the pykka logger was somehow buggered but in actual fact, file configuration caused the issue. See the last comment on this issue.

    I feel the solution could be documented in Pykka, mainly because it was non-trivial for me to find out that:

    • how logging was supposed to work when a library obtains their own logger, e.g. pykka
    • whether logging causes problems when working with multiple threads (it doesn't)
    • whether logging.getLogger('pykka') gets the exact instance of the logger as Pykka does (it does)
    • how then to set the logger's level to DEBUG; how the root logger's level also needs to be set to DEBUG for messages to show.
    docs 
    opened by fatuhoku 4
  • Initialising an actor system with cyclic references

    Initialising an actor system with cyclic references

    Pykka's API (.start method) doesn't really let the user make actor systems with cyclic referential relationships like:

    a -> b -> c -> a
    

    where a -> b denotes that actor a holds a reference to actor b (probably for the better!)

    However, I find this useful.

    What is idiomatic Pykka for initialising such a ring of actors?

    opened by fatuhoku 4
  • Delayed messages

    Delayed messages

    This PR implements delayed message delivery, useful for creating event loops which can still be terminated at a moment's notice. Possibly fixes #44. Also fixes an unrelated bug in eventlet.Event that caused event.wait() to result in an AttributeError.

    Supporting delay in ask/tell is pretty straightforward, but doing it for proxy() requires some additional indirection. It is in the commit by itself now, because I understand that the approach I used may be questionable; I also hasn't changed the docs/tests because there is a probability the interface will be changed. Currently one would use delayed proxies as

    proxy = actor_ref.proxy(extended=True)
    proxy.delayed(1).something()
    proxy.delayed(2).some.attr = 1
    

    All the introspection is only done once when proxy_base is created.

    This PR has some intersection of functionality with PR #95, but is simpler and gives actors more control of the process (specifically, it is more convenient for event loop organization).

    opened by fjarri 9
  • Akka style `Become` and `Unbecome`

    Akka style `Become` and `Unbecome`

    Based on this issue: https://github.com/jodal/pykka/issues/38

    This PR adds two methods to the standard Actor class:

    1. Method _become(self, func, *args, discard_old=True) changes message handing behaviour to a specified function.
    • funcparameter is a callable function that should be executed on message receive.
    • *args parameter allows us to pass any values we need to the function and to avoid using "mutable" class properties to keep actor state (surely, there is no immutability in Python, but still class properties are not used).
    • discard_old=True parameter says whether it should to replace actual behaviour with this new handler completely or it should stash handlers in a handlers stack to be able to return back to them.
    1. Method _unbecome(self) changes actor's message processing strategy to the previous one.
    • If _become was used with discard_old=True option, _unbecome switches behaviour to the standard on_receive method.
    • If _become was used with discard_old=False option and there are n message handlers in stack, behaviour will change to the handler n-1.
    • If _become wasn't used, and actual behaviour is the default one, nothing happens.

    These methods allow to model an FSM with an actor, using _become and _unbecome to switch between states.

    opened by akatashev 1
  • Akka-style message Scheduler

    Akka-style message Scheduler

    First of all, thanks for Pykka, it's really nice! There is this issue about auto-scheduling: https://github.com/jodal/pykka/issues/53

    I needed this functionality for my project as well, because I believe, that an ability to use schedulers to retransmit messages, schedule job executions and so on, is quite a bit part of Akka, so I created it for myself and I hope, it could be useful for Pykka community as well.

    Basically, I implemented the simplest versions of Cancellable, Scheduler.scheduleOnce, Scheduler.scheduleWithFixedDelay and Scheduler.scheduleAtFixedRate from Akka.

    There are 3 schedulers for 3 different kinds of Actors: ThreadingScheduler - based on threading.Timer. EventletScheduler - based on eventlet.spawn_after. GeventScheduler - based on gevent.spawn_later.

    opened by akatashev 5
  • Implementation of priority queues/maiboxes

    Implementation of priority queues/maiboxes

    I had the need for a priority mailbox. I implemented priority queues pretty raw with touching the core part as less as possible.

    For the tell ask messages it looks like that:

    actor_ref.ask({'pykka_priority': 10, 'num': 1})
    

    For proxies it is usable with a small decorator:

    class AnProxyActor(ThreadingActorPriorityMailbox):
        def __init__(self):
            ThreadingActorPriorityMailbox.__init__(self)
            self.call_order = []
    
        @priority(40)
        def important(self):
            time.sleep(0.4)
            self.call_order.append('important')
    
        @priority(30)
        def more_important(self):
            time.sleep(0.4)
            self.call_order.append('more_important')
    

    Looking forward to your feedback.

    Its here: https://github.com/julian-r/pykka/tree/priority_queue

    enhancement 
    opened by julian-r 2
  • Pykka actors auto scheduling

    Pykka actors auto scheduling

    Hello pykka contributors,

    is there any equivalent and easy way to implement some message scheduling like we have in akka lib ;

    InjectorAkkaSystemActivator.getSystem().scheduler().schedule(Duration.Zero(),
                          Duration.create(millisecondPeriod, TimeUnit.MILLISECONDS),
                          actor,
                          message,
                          InjectorAkkaSystemActivator.getSystem().dispatcher(),
                          null));
    

    Or do we need to implement this kind of scheduler ourself ? Do you have some best practices on that topic ?

    Cheers,

    Mathilde

    enhancement 
    opened by mffrench 3
Releases(v3.1.1)
  • v3.1.1(May 27, 2022)

    Bugfix release.

    • Installs from the source tarball using the setup.py file generated by Poetry installed setup.cfg and tox.ini into site-packages. The workaround for this was to simply not include those files in the source tarball. (Fixes: #172)
    Source code(tar.gz)
    Source code(zip)
  • v3.1.0(May 27, 2022)

    Breaking changes

    • Remove support for Python 3.6. It reached end-of-life in December 2021. (PR: #159)

    Bug fixes

    • Include docs, examples, and tests in the source release. (Fixes: #171)

    Development environment

    • Require mypy 0.960 and use the latest typing features, as these seem to work nicely even on Python 3.7, given that the typing information is in separate *.pyi files and that you have a recent mypy version.
    Source code(tar.gz)
    Source code(zip)
  • v3.0.2(Oct 8, 2021)

    Bugfix release.

    • Add support for Python 3.10. Tests are now run on Python 3.10 too. No other changes required.
    • Minor reorganization of docs.
    Source code(tar.gz)
    Source code(zip)
  • v3.0.1(May 4, 2021)

  • v3.0.0(Mar 28, 2021)

    Breaking changes

    • Remove support for Python 2.7. It reached end-of-life in January 2020. (PR: #87)
    • Remove support for Python 3.5. It reached end-of-life in September 2020. (PR: :#89)
    • Remove support for running actors on top of eventlet. This was deprecated in Pykka 2.0.3. (PR: #111)
    • Remove support for running actors on top of gevent. This was deprecated in Pykka 2.0.3 (PR: #111)
    • Remove support for automatically upgrading the internal message format used by Pykka < 2.0 to the message types used by Pykka >= 2.0. (PR: #88)

    Features

    • Include complete type hint stubs for all public APIs in the PyPI distribution. (PR: #92)

    Development environment

    • Remove PyPy from the test matrix. There are no known changes that should cause Pykka to stop working on PyPy, but we will no longer spend any effort to keep CI for PyPy running. (PR: #113)
    Source code(tar.gz)
    Source code(zip)
  • v2.0.3(Mar 7, 2021)

    Bugfix release.

    • Mark eventlet and gevent support as deprecated. The support will be removed in Pykka 3.0.

      These were somewhat interesting ways to implement concurrency in Python when Pykka was conceived in 2011. Today, it is unclear it these libraries still have any mindshare or if keeping the support for them just adds an unnecessary burden to Pykka's maintenance.

    • Include Python 3.9 in the test matrix. (PR: #98)

    • Add missing None default value for the timeout keyword argument to pykka.eventlet.EventletEvent.wait(), so that it matches the threading.Event API. (PR: #91)

    Source code(tar.gz)
    Source code(zip)
  • v2.0.2(Mar 7, 2021)

  • v2.0.1(Mar 7, 2021)

  • v2.0.0(Mar 7, 2021)

    Major feature release.

    Dependencies

    • Drop support for Python 2.6, 3.2, 3.3, and 3.4. All have reached their end of life and do no longer receive security updates.

    • Include CPython 3.5, 3.6, 3.7, and 3.8 pre-releases, and PyPy 3.5 in the test matrix.

    • Include gevent and Eventlet tests in all environments. Since Pykka was originally developed, both have grown support for Python 3 and PyPy.

    • On Python 3, import Callable and Iterable from collections.abc instead of collections. This fixes a deprecation warning on Python 3.7 and prepares for Python 3.8.

    Actors

    • Actor messages are no longer required to be dict objects. Any object type can be used as an actor message. (Fixes: #39, #45, PR: #79)

      For existing code, this means that pykka.Actor.on_receive() implementations should no longer assume the received message to be a dict, and guard with the appropriate amount of isinstance() checks. As an existing application will not observe any new message types before it starts using them itself, this is not marked as backward incompatible.

    Proxies

    • Backwards incompatible: Avoid accessing actor properties when creating a proxy for the actor. For properties with side effects, this is a major bug fix. For properties which do heavy work, this is a major startup performance improvement.

      This is backward incompatible if you in a property getter returned an object instance with the pykka_traversable marker. Previously, this would work just like a traversable attribute. Now, the property always returns a future with the property getter's return value.

    • Fix infinite recursion when creating a proxy for an actor with an attribute or method replaced with a unittest.mock.Mock without a spec defined. (Fixes: #26, #27)

    • Fix infinite recursion when creating a proxy for an actor with an attribute that was itself a proxy to the same actor. The attribute will now be ignored and a warning log message will ask you to consider making the self-proxy private. (Fixes: #48)

    • Add pykka.CallableProxy.defer() to support method calls through a proxy with pykka.ActorRef.tell() semantics. (Contributed by Andrey Gubarev. Fixes: #63. PR: #72)

    • Add pykka.traversable() for marking an actor's attributes as traversable when used through actor proxies. The old way of manually adding a pykka_traversable attribute to the object to be traversed still works, but the new function is recommended as it provides protection against typos in the marker name, and keeps the traversable marking in the actor class itself. (PR: #81)

    Futures

    • Backwards incompatible: pykka.Future.set_exception() no longer accepts an exception instance, which was deprecated in 0.15. The method can be called with either an exc_info tuple or None, in which case it will use sys.exc_info() to get information on the current exception.

    • Backwards incompatible: pykka.Future.map() on a future with an iterable result no longer applies the map function to each item in iterable. Instead, the entire future result is passed to the map function. (Fixes: :issue:64)

      To upgrade existing code, make sure to explicitly apply the core of your map function to each item in the iterable:

      >>> f = pykka.ThreadingFuture()
      >>> f.set([1, 2, 3])
      >>> f.map(lambda x: x + 1).get()  # Pykka < 2.0
      [2, 3, 4]
      >>> f.map(lambda x: [i + 1 for i in x]).get()  # Pykka >= 2.0
      [2, 3, 4]
      

      This change makes it easy to use :meth:pykka.Future.map to extract a field from a future that returns a dict:

      >>> f = pykka.ThreadingFuture()
      >>> f.set({'foo': 'bar'})
      >>> f.map(lambda x: x['foo']).get()
      'bar'
      

      Because dict is an iterable, the now removed special handling of iterables made this pattern difficult to use.

    • Reuse result from pykka.Future.filter(), pykka.Future.map(), and pykka.Future.reduce(). Recalculating the result on each call to pykka.Future.get() is both inconsistent with regular futures and can cause problems if the function is expensive or has side effects. (Fixes: #32)

    • If using Python 3.5+, one can now use the await keyword to get the result from a future. (Contributed by Joshua Doncaster-Marsiglio. PR: #78)

    Logging

    • Pykka's use of different log levels has been documented.

    • Exceptions raised by an actor that are captured into a reply future are now logged on the logging.INFO level instead of the logging.DEBUG level. This makes it possible to detect potentially unhandled exceptions during development without having to turn on debug logging, which can have a low signal-to-noise ratio. (Contributed by Stefan Möhl. Fixes: #73)

    Gevent support

    • Ensure that the original traceback is preserved when an exception is returned through a future from a Gevent actor. (Contributed by Arne Brutschy. Fixes: #74, PR: #75)

    Internals

    • Backwards incompatible: Prefix all internal modules with _. This is backward-incompatible if you have imported objects from other import paths than what is used in the documentation.

    • Port tests to pytest.

    • Format code with Black.

    • Change internal messaging format from dict to namedtuple. (PR: #80)

    Source code(tar.gz)
    Source code(zip)
  • v1.2.1(Mar 7, 2021)

    • Increase log level of pykka.debug.log_thread_tracebacks() debugging helper from logging.INFO to logging.CRITICAL.

    • Fix errors in docs examples. (PR: #29, #43)

    • Fix typos in docs.

    • Various project setup and development improvements.

    Source code(tar.gz)
    Source code(zip)
  • v1.2.0(Mar 7, 2021)

    • Enforce that multiple calls to pykka.Future.set() raises an exception. This was already the case for some implementations. The exception raised is not specified.

    • Add pykka.Future.set_get_hook().

    • Add pykka.Future.filter(), pykka.Future.join(), pykka.Future.map(), and pykka.Future.reduce() as convenience methods using the new pykka.Future.set_get_hook() method.

    • Add support for running actors based on eventlet greenlets. See pykka.eventlet for details. Thanks to Jakub Stasiak for the implementation.

    • Update documentation to reflect that the reply_to field on the message is private to Pykka. Actors should reply to messages simply by returning the response from pykka.Actor.on_receive(). The internal field is renamed to pykka_reply_to to avoid collisions with other message fields. It is also removed from the message before the message is passed to pykka.Actor.on_receive(). Thanks to Jakub Stasiak.

    • When messages are left in the actor inbox after the actor is stopped, those messages that are expecting a reply are now rejected by replying with a pykka.ActorDeadError exception. This causes other actors that are blocking on the returned pykka.Future without a timeout to raise the exception instead of waiting forever. Thanks to Jakub Stasiak.

      This makes the behavior of messaging an actor around the time it is stopped more consistent:

      • Messaging an already dead actor immediately raises pykka.ActorDeadError.

      • Messaging an alive actor that is stopped before it processes the message will cause the reply future to raise pykka.ActorDeadError.

      Similarly, if you ask an actor to stop multiple times, and block on the responses, all the messages will now get a reply. Previously only the first message got a reply, potentially making the application wait forever on replies to the subsequent stop messages.

    • When pykka.ActorRef.ask() is used to asynchronously message a dead actor (e.g. block=False), it will no longer immediately raise pykka.ActorDeadError. Instead, it will return a future and fail the future with the pykka.ActorDeadError exception. This makes the interface more consistent, as you'll have one instead of two ways the call can raise exceptions under normal conditions. If pykka.ActorRef.ask is called synchronously (e.g. block=True), the behavior is unchanged.

    • A change to pykka.ActorRef.stop() reduces the likelihood of a race condition when asking an actor to stop multiple times by not checking if the actor is dead before asking it to stop, but instead, just go ahead and leave it to pykka.ActorRef.tell() to do the alive-or-dead check a single time, and as late as possible.

    • Change pykka.ActorRef.is_alive() to check the actor's runnable flag instead of checking if the actor is registered in the actor registry.

    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Mar 7, 2021)

    • An exception raised in pykka.Actor.on_start() didn't stop the actor properly. Thanks to Jay Camp for finding and fixing the bug.

    • Make sure exceptions in pykka.Actor.on_stop() and pykka.Actor.on_failure() is logged.

    • Add pykka.ThreadingActor.use_daemon_thread flag for optionally running an actor on a daemon thread, so that it doesn't block the Python program from exiting. (Fixes: #14)

    • Add pykka.debug.log_thread_tracebacks() debugging helper. (Fixes: #17)

    Source code(tar.gz)
    Source code(zip)
  • v1.0.1(Mar 7, 2021)

  • v1.0.0(Mar 7, 2021)

    • Backwards incompatible: Removed pykka.VERSION and pykka.get_version(), which have been deprecated since v0.14. Use pykka.__version__ instead.

    • Backwards incompatible: Removed pykka.ActorRef.send_one_way() and pykka.ActorRef.send_request_reply(), which have been deprecated since v0.14. Use pykka.ActorRef.tell() and pykka.ActorRef.ask() instead.

    • Backwards incompatible: Actors no longer subclass threading.Thread or gevent.Greenlet. Instead, they have a thread or greenlet that executes the actor's main loop.

      This is backward incompatible because you no longer have access to fields/methods of the thread/greenlet that runs the actor through fields/methods on the actor itself. This was never advertised in Pykka's docs or examples, but the fields/methods have always been available.

      As a positive side effect, this fixes an issue on Python 3.x, that was introduced in Pykka 0.16, where pykka.ThreadingActor would accidentally override the method threading.Thread._stop().

    • Backwards incompatible: Actors that override pykka.Actor.__init__() must call the method they override. If not, the actor will no longer be properly initialized. Valid ways to call the overridden __init__() method include::

      super().__init__()
      # or
      pykka.ThreadingActor.__init__()
      # or
      pykka.gevent.GeventActor.__init__()
      
    • Make pykka.Actor.__init__() accept any arguments and keyword arguments by default. This allows you to use super() in __init__() like this:

      super().__init__(1, 2, 3, foo='bar')
      

      Without this fix, the above use of super() would cause an exception because the default implementation of __init__() in pykka.Actor would not accept the arguments.

    • Allow all public classes and functions to be imported directly from the pykka module. E.g. from pykka.actor import ThreadingActor can now be written as from pykka import ThreadingActor. The exception is pykka.gevent, which still needs to be imported from its own package due to its additional dependency on gevent.

    Source code(tar.gz)
    Source code(zip)
  • v0.16(Mar 7, 2021)

    • Let actors access themselves through a proxy. See the pykka.ActorProxy documentation for use cases and usage examples. (Fixes: #9)

    • Give proxies direct access to the actor instances for inspecting available attributes. This access is only used for reading and works since both threading and gevent based actors share memory with other actors. This reduces the creation cost for proxies, which is mostly visible in test suites that are starting and stopping lots of actors. For the Mopidy test suite, the run time was reduced by about 33%. This change also makes self-proxying possible.

    • Fix bug where pykka.Actor.stop() called by an actor on itself did not process the remaining messages in the inbox before the actor stopped. The behavior now matches the documentation.

    Source code(tar.gz)
    Source code(zip)
  • v0.15(Mar 7, 2021)

    • Change the argument of pykka.Future.set_exception() from an exception instance to an exc_info three-tuple. Passing just an exception instance to the method still works, but it is deprecated and may be unsupported in a future release.

    • Due to the above change pykka.Future.get() will now reraise exceptions with complete traceback from the point when the exception was first raised and not just a traceback from when it was reraised by get(). (Fixes: #10)

    Source code(tar.gz)
    Source code(zip)
  • v0.14(Mar 7, 2021)

    • Add pykka.__version__ to conform with PEP 396. This deprecates pykka.VERSION and pykka.get_version().

    • Add pykka.ActorRef.tell() method in favor of now deprecated pykka.ActorRef.send_one_way().

    • Add pykka.ActorRef.ask() method in favor of now deprecated pykka.ActorRef.send_request_reply().

    • pykka.ThreadingFuture.set() no longer makes a copy of the object set on the future. The setter is urged to either only pass immutable objects through futures or copy the object himself before setting it on the future. This is a less safe default, but it removes unnecessary overhead in speed and memory usage for users of immutable data structures. For example, the Mopidy test suite of about 1000 tests, many of which are using Pykka, is still passing after this change, but the test suite runs approximately 20% faster.

    Source code(tar.gz)
    Source code(zip)
  • v0.13(Mar 7, 2021)

  • v0.12.4(Mar 7, 2021)

    • Change and document order in which pykka.ActorRegistry.stop_all() stops actors. The new order is the reverse of the order the actors were started in. This should make stop_all() work for programs with simple dependency graphs in between the actors. For applications with more complex dependency graphs, the developer still needs to pay attention to the shutdown sequence. (Fixes: #8)
    Source code(tar.gz)
    Source code(zip)
  • v0.12.3(Mar 7, 2021)

    • If an actor that was stopped from pykka.Actor.on_start(), it would unregister properly, but start the receive loop and forever block on receiving incoming messages that would never arrive. This left the thread alive and isolated, ultimately blocking a clean shutdown of the program. The fix ensures that the receive loop is never executed if the actor is stopped before the receive loop is started.

    • Set the thread name of any pykka.ThreadingActor to PykkaActorThread-N instead of the default Thread-N. This eases debugging by clearly labeling actor threads in e.g. the output of threading.enumerate().

    • Add utility method pykka.ActorRegistry.broadcast() which broadcasts a message to all registered actors or to a given class of registered actors. (Fixes: #7)

    • Allow multiple calls to pykka.ActorRegistry.unregister() with the same pykka.actor.ActorRef as argument without throwing a ValueError. (Fixes: #5)

    • Make the pykka.ActorProxy's reference to its pykka.ActorRef public as pykka.ActorProxy.actor_ref. The ActorRef instance was already exposed as a public field by the actor itself using the same name, but making it public directly on the proxy makes it possible to do e.g. proxy.actor_ref.is_alive() without waiting for a potentially dead actor to return an ActorRef instance you can use. (Fixes: #3)

    Source code(tar.gz)
    Source code(zip)
  • v0.12.2(Mar 7, 2021)

    • Actors are now registered in pykka.registry.ActorRegistry before they are started. This fixes a race condition where an actor tried to stop and unregister itself before it was registered, causing an exception in ActorRegistry.unregister.
    Source code(tar.gz)
    Source code(zip)
  • v0.12.1(Mar 7, 2021)

  • v0.12(Mar 7, 2021)

Owner
Stein Magnus Jodal
Expressing myself mostly in Python, JavaScript, and a bit of Rust. Web/infrastructure/IoT. Debian Developer. Creator of @mopidy.
Stein Magnus Jodal
aiomisc - miscellaneous utils for asyncio

aiomisc - miscellaneous utils for asyncio Miscellaneous utils for asyncio. The complete documentation is available in the following languages: English

aiokitchen 295 Jan 08, 2023
Simple package to enhance Python's concurrent.futures for memory efficiency

future-map is a Python library to use together with the official concurrent.futures module.

Arai Hiroki 2 Nov 15, 2022
SCOOP (Scalable COncurrent Operations in Python)

SCOOP (Scalable COncurrent Operations in Python) is a distributed task module allowing concurrent parallel programming on various environments, from h

Yannick Hold 573 Dec 27, 2022
rosny is a lightweight library for building concurrent systems.

rosny is a lightweight library for building concurrent systems. Installation Tested on: Linux Python = 3.6 From pip: pip install rosny From source: p

Ruslan Baikulov 6 Oct 05, 2021
Jug: A Task-Based Parallelization Framework

Jug: A Task-Based Parallelization Framework Jug allows you to write code that is broken up into tasks and run different tasks on different processors.

Luis Pedro Coelho 387 Dec 21, 2022
A concurrent sync tool which works with multiple sources and targets.

Concurrent Sync A concurrent sync tool which works similar to rsync. It supports syncing given sources with multiple targets concurrently. Requirement

Halit ÅžimÅŸek 2 Jan 11, 2022
A curated list of awesome Python asyncio frameworks, libraries, software and resources

Awesome asyncio A carefully curated list of awesome Python asyncio frameworks, libraries, software and resources. The Python asyncio module introduced

Timo Furrer 3.8k Jan 08, 2023
Raise asynchronous exceptions in other thread, control the timeout of blocks or callables with a context manager or a decorator

stopit Raise asynchronous exceptions in other threads, control the timeout of blocks or callables with two context managers and two decorators. Attent

Gilles Lenfant 97 Oct 12, 2022
A lightweight (serverless) native python parallel processing framework based on simple decorators and call graphs.

A lightweight (serverless) native python parallel processing framework based on simple decorators and call graphs, supporting both control flow and dataflow execution paradigms as well as de-centrali

102 Jan 06, 2023
Unsynchronize asyncio by using an ambient event loop, or executing in separate threads or processes.

unsync Unsynchronize asyncio by using an ambient event loop, or executing in separate threads or processes. Quick Overview Functions marked with the @

Alex Sherman 802 Dec 28, 2022
Trio – a friendly Python library for async concurrency and I/O

Trio – a friendly Python library for async concurrency and I/O The Trio project aims to produce a production-quality, permissively licensed, async/awa

5k Jan 07, 2023
Thread-safe asyncio-aware queue for Python

Mixed sync-async queue, supposed to be used for communicating between classic synchronous (threaded) code and asynchronous

aio-libs 665 Jan 03, 2023
Parallelformers: An Efficient Model Parallelization Toolkit for Deployment

Parallelformers: An Efficient Model Parallelization Toolkit for Deployment

TUNiB 559 Dec 28, 2022
AnyIO is an asynchronous networking and concurrency library that works on top of either asyncio or trio.

AnyIO is an asynchronous networking and concurrency library that works on top of either asyncio or trio. It implements trio-like structured concurrenc

Alex Grönholm 1.1k Jan 06, 2023
Ultra fast asyncio event loop.

uvloop is a fast, drop-in replacement of the built-in asyncio event loop. uvloop is implemented in Cython and uses libuv under the hood. The project d

magicstack 9.1k Jan 07, 2023
A Python package for easy multiprocessing, but faster than multiprocessing

MPIRE, short for MultiProcessing Is Really Easy, is a Python package for multiprocessing, but faster and more user-friendly than the default multiprocessing package.

753 Dec 29, 2022
🌀 Pykka makes it easier to build concurrent applications.

🌀 Pykka Pykka makes it easier to build concurrent applications. Pykka is a Python implementation of the actor model. The actor model introduces some

Stein Magnus Jodal 1.1k Dec 30, 2022
Backport of the concurrent.futures package to Python 2.6 and 2.7

This is a backport of the concurrent.futures standard library module to Python 2. It does not work on Python 3 due to Python 2 syntax being used in th

Alex Grönholm 224 Nov 07, 2022
Python Multithreading without GIL

Multithreaded Python without the GIL

Sam Gross 2.3k Jan 05, 2023