Skip to main content

ZProc - Process on steroids

Project description

ZProc - Process on steroids

Multi-Processing how it should've been.

If you're wondering, ZProc is short for Zero Process

Philosophy

History

Traditional Multi Processing was mostly, built on the principle of shared memory.
This might sound odd, but shared memory violates the laws of Physics itself.
Don't believe me? watch this (from Joe Armstrong, the creator of Erlang)

The solution presented by Erlang, (and ZMQ) is the notion of message passing for achieving parallelism, or at least concurrency.
Yes, they are different things.

Now

Message passing can be tedious, and often un-pythonic.
This is where ZProc comes in.

It provides a middle ground between message passing and shared memory.

It does message passing, without you ever knowing that it's doing it.
It provides you a global dict which we like to call state.
The state is not shared memory, and works purely on message passing.

If you're a CS majaor, you might recognize this as the Actor Model.
ZProc doesn't blindly follow it, but it you can think of it as such.

The zen of zero

generally, "zero" refers to the culture of minimalism that permeates the project. We add power by removing complexity rather than by exposing new functionality.

Install

pip install zproc

License: MIT License (MIT)
Requires: Python >=3.5

Documentation

Read the docs

Examples

A great way to see zproc in action is through the examples
They should be pretty self-explanatory.

🔖

Features

  • 🌠   Global State

    • Globally synchronized state (dict), without using shared memory.
    • 🔖
  • 🌠   Asynchronous paradigms without async def

    • Build any combination of synchronous and asynchronous systems.
    • watch for changes in state, without Busy Waiting.
    • 🔖
  • 🌠   Process management

    • Process Factory
    • Remembers to kill processes when exiting, for general peace. (even when they're nested)
    • Keeps a record of processes created using ZProc.
    • 🔖
  • 🌠   Atomic Operations

    • Perform an arbitrary number of operations on state as a single, atomic operation.
    • 🔖

Atomicity

The elephant in the room, race-conditions.

In ZProc world, a single dict operation is guaranteed™ to be atomic.

But, in real world applications require arbitrary number of operations to be atomic.

Exhibit A

def increment(step):
    state.count += step

increment(5)

increment() might look like a single operation, but don't get fooled! (They're 2)

  1. __getitem__ -> get 'count'

  2. __setitem__ -> set 'count' to <count> + 1

__getitiem__ and __setitem__ are guarateed™ to be atomtic on their own, but NOT in conjunction.

If these operations are not done atomically, it exposes the possiblity of other Processes trying to do operations between "1" and "2"

Clearly, a remedy is required.


With ZProc, it's dead simple.

Let's make some changes to our example..

@state.atomify()
def increment(state, step):
    state.count += step

increment(5)

If it wasn't clear, @state.atomify() makes any arbitrary function, an atomic operation on the state.

🔖

Caveats

  • The state only gets updated if you do it directly. This means that if you mutate objects inside the state, they wont get updated in global state.
  • It runs an extra daemonic server for managing the state. Its fairly lightweight though, and shouldn't add too much weight to your application.
  • The state should be pickle-able
  • Missing state updates when using state.get_when_*, if updates are too fast.
    • Current API is not intended for this type of use-case.
    • Work is being done to expose new API that will allow you to watch for every singe update, no matter when they occur

FAQ

  • fast?
    • plenty, since its written with ZMQ.
    • See luck_test.py example for a taste.
  • stable?
    • The project itself is stable, but the API is NOT.
  • real?
    • YES. It works.
    • 🔖
  • Windows / Mac compatible?
    • I honestly don't know. Please tell me.

Inner Workings

  • The process(s) communicate over zmq sockets, over ipc://.

  • Zproc runs a zproc server, which is responsible for storing and managing the state.

    • update the state whenever another process updates it.
    • transmit the state whenever a process needs to access it.
  • Overall, the zproc server helps create an illusion of a global shared state when actually, it isn't shared at all!

  • If a process wishes to synchronize at a certain condition, it can attach a handler to the zproc server.

    • The zproc server will check the condition on all state-changes.
    • If the condition is met, the zproc server shall open a tunnel to the application and send the state back.
    • zmq sockets block your application until that tunnel is opened.

Local development

git clone https://github.com/pycampers/zproc.git
cd zproc
pipenv install

Build documentation

Assuming you have sphinx installed (Linux)

cd docs
pipenv run ./build.sh

Thanks

  • Thanks to pieter hintjens, for his work on the ZeroMQ library and for his amazing book.
  • Thanks to tblib, ZProc can raise First-class Exceptions from the zproc server!
  • Thanks to psutil, ZProc can handle nested procesess!

Buy Me A Coffee

🐍🏕️

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

zproc-0.3.2.tar.gz (13.1 kB view hashes)

Uploaded Source

Built Distribution

zproc-0.3.2-py2.py3-none-any.whl (22.7 kB view hashes)

Uploaded Python 2 Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page