tractor ******* The Python async-native multi-core system *you always wanted*. https://actions-badge.atrox.dev/goodboy/tractor/goto https://tractor.readthedocs.io/en/latest/?badge=latest ``tractor`` is a `structured concurrent `_ “`actor model `_” built on `trio `_ and `multi-processing `_. It is an attempt to pair `trionic `_ `structured concurrency `_ with distributed Python. You can think of it as a ``trio`` *-across-processes* or simply as an opinionated replacement for the stdlib’s ``multiprocessing`` but built on async programming primitives from the ground up. Don’t be scared off by this description. ``tractor`` **is just ``trio``** but with nurseries for process management and cancel-able IPC. If you understand how to work with ``trio``, ``tractor`` will give you the parallelism you’ve been missing. ``tractor``’s nurseries let you spawn ``trio`` *“actors”*: new Python processes which each run a ``trio`` scheduled task tree (also known as an `async sandwich `_ - a call to ``trio.run()``). That is, each “*Actor*” is a new process plus a ``trio`` runtime. “Actors” communicate by exchanging asynchronous `messages `_ and avoid sharing state. The intention of this model is to allow for highly distributed software that, through the adherence to *structured concurrency*, results in systems which fail in predictable and recoverable ways. The first step to grok ``tractor`` is to get the basics of ``trio`` down. A great place to start is the `trio docs `_ and this `blog post `_. Install ======= No PyPi release yet! :: pip install git+git://github.com/goodboy/tractor.git Alluring Features ================= * **It’s just** ``trio``, but with SC applied to processes (aka “actors”) * Infinitely nesteable process trees * Built-in API for inter-process streaming * A (first ever?) “native” multi-core debugger for Python using `pdb++ `_ * (Soon to land) ``asyncio`` support allowing for “infected” actors where *trio* drives the *asyncio* scheduler via the astounding “`guest mode `_” The example you’re probably after… ================================== It seems the initial query from most new users is “how do I make a worker pool thing?”. ``tractor`` is built to handle any SC process tree you can imagine; the “worker pool” pattern is a trivial special case: # TODO: workerpool example .. code:: """ Run with a process monitor from a terminal using: $TERM -e watch -n 0.1 "pstree -a $$" & python examples/parallelism/we_are_processes.py && kill $! """ from multiprocessing import cpu_count import os import tractor import trio async def target(): print(f"Yo, i'm '{tractor.current_actor().name}' " f"running in pid {os.getpid()}") await trio.sleep_forever() async def main(): async with tractor.open_nursery() as n: for i in range(cpu_count()): await n.run_in_actor(target, name=f'worker_{i}') print('This process tree will self-destruct in 1 sec...') await trio.sleep(1) # you could have done this yourself raise Exception('Self Destructed') if __name__ == '__main__': try: trio.run(main) except Exception: print('Zombies Contained') Feel like saying hi? ==================== This project is very much coupled to the ongoing development of ``trio`` (i.e. ``tractor`` gets most of its ideas from that brilliant community). If you want to help, have suggestions or just want to say hi, please feel free to reach us in our `matrix channel `_. If matrix seems too hip, we’re also mostly all in the the `trio gitter channel `_!