Skip to main content

Helper for running functions in a concurrent loop.

Project description

README

Package overview

concurrent_loop provides helpers for running functions in a continuous loop in a separate thread or process.

Installation

pip install concurrent_loop

Example usage

Code set up

The following code creates a class which increments a counter in a looped process using the ProcessLoop class (replace with ThreadLoop instead to run in a separate thread rather than process).

from concurrent_loop.loops import ProcessLoop


class CounterIterator(object):
  """
  Iterates a counter in a loop that runs in an independent process.
  """
  counter = 0  # Value to be incremented

  concurrent_loop_runner = ProcessLoop(100)  # Set up the controller that
  # will run any requested function every 100 ms in a separate process.

  def _increment(self, increment_val):
    """
    Increment the internal counter once and print value. 

    This will be run repeatedly in a process.

    Args:
      increment_val (int): The value to increment the internal counter by.
    """
    self.counter += increment_val
    print(self.counter)

  def concurrent_start(self):
    """
    Run the _increment() function in the process loop.
    """
    # Increments the internal counter in steps of 2. Arg must be supplied
    # as a tuple.
    self.concurrent_loop_runner.start(self._increment, (2,))

  def concurrent_stop(self):
    """
    Stop the process loop.
    """
    self.concurrent_loop_runner.stop()

Start up

Finally, in the main code:

iter = CounterIterator()

iter.concurrent_start()
sleep(1)
iter.concurrent_stop()

Exception handling

When an exception is raised in the underlying concurrent loop, the concurrent loop stops, but the main process thread has no automatic knowledge of it. The user code can read any exceptions raised from the ThreadLoop. exception or ProcessLoop.exception property.

In the above example, we would read:

iter.concurrent_loop_runner.exception

Asynchronous communication with Queue()

Both multiprocessing.Queue and queue.Queue allow asynchronous communications with the concurrent loop. However, to ensure correct functioning of the queue, the following rules must be adhered to:

  • The class that calls the ThreadLoop or ProcessLoop (which is the CounterIterator class in above example) must create the Queue instance as an instance attribute, and not as a class attribute.
  • The Queue instance must be passed into looped function (the _increment function in above example) as a function parameter, and not called from the looped function as an attribute.

To extend the above example so that _increment function sends the counter value to a results queue on each loop, we do the following.

Import the queue module (for this example, we'll use the simpler multiprocessing.Queue):

from multiprocessing import Queue

Instantiate a results queue in CounterIterator.__init__:

class CounterIterator(object):
  _results_q = None

  def __init__(self):
    self._results_q = Queue()

Modify the _increment function to put the counter value into the results queue:

  def _increment(self, res_q, increment_val)
    self.counter += increment_val
    res_q.put_nowait(self._counter)

Pass the results queue from concurrent_start method into the _increment function.

  def concurrent_start(self):
    self.concurrent_loop_runner.start(self._increment, (self._results_q, 2))

Define a counter getter that gets the counter value from the FIFO results queue:

  @property
  def counter(self):
    return self._results_q.get()

In the main code, to print out the counter value from the first 10 loops:

iter = CounterIterator()

iter.concurrent_start()

for _ in range(10):
  print(iter.counter)

iter.concurrent_stop()

Who do I talk to?

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

concurrent_loop-1.1.4.tar.gz (18.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

concurrent_loop-1.1.4-py3-none-any.whl (18.7 kB view details)

Uploaded Python 3

File details

Details for the file concurrent_loop-1.1.4.tar.gz.

File metadata

  • Download URL: concurrent_loop-1.1.4.tar.gz
  • Upload date:
  • Size: 18.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.10.6

File hashes

Hashes for concurrent_loop-1.1.4.tar.gz
Algorithm Hash digest
SHA256 02cded5f1a57b9c3a863fda0f1063fb26ebe85b48ece04292f9e9fbf4407f8d4
MD5 0013a0e1dbd00ab8800c7ee681a0235e
BLAKE2b-256 6d8cf2eeff9a6624ce3fa9c9ab745cf0dc7170fa6c8d8602f2080a30c5156a0a

See more details on using hashes here.

File details

Details for the file concurrent_loop-1.1.4-py3-none-any.whl.

File metadata

File hashes

Hashes for concurrent_loop-1.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 cc08439ea224512dab2294ba77d4a505a4fd2c4b673b006d73fc0e846ef2c173
MD5 68b550acf57a1e7ec5ca0e4a5d5c421c
BLAKE2b-256 5605f61cd25dd782cbb5347ab6730f07525f71a016311a24c27e8fda755fb59a

See more details on using hashes here.

Supported by

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