Skip to content

tedious ramblings

The blog of Robert Hafner

Menu
  • Projects
  • Resume
  • Sponsor
  • Archives
  • About
Menu

Simple Multiprocessing with QuasiQueue

Posted on February 2, 2023February 1, 2023 by Robert Hafner

My third open source project this week is one of my favorites. QuasiQueue is a MultiProcessing library for Python that makes it super easy to have long running MultiProcess jobs. QuasiQueue handles process creation and cleanup, signal management, cross process communication, and all the other garbage that makes people hate dealing with multiprocessing.

I started on this library a couple of years ago and have pulled it out to use as the basis for multiple projects. QuasiQueue works by splitting the work into two components- the main process whose job it is to feed a Queue with work, and then read processes that take work off of the Queue to run. All the developers have to do is create two functions, a Reader and a Writer, and QuasiQueue will handle the rest.

QuasiQueue can be used for a number of purposes-

  • Server/Client communication where the Writer waits for requests to come in and then passes the incoming sockets to the Readers. You could build an special purpose multiprocess HTTP server (or any protocol) this way.
  • Dynamic Crawlers to constantly crawl and update data. I used this to crawl my Twitter followers and build network graphs to dynamically generate lists, as one really silly example.
  • Local data processing, such as running image processing.

QuasiQueue is meant to be extremely simple- writing programs that utilize QuasiQueue is as simple as defining two functions. The output of the writer function will end up feeding the reader function. The only limitations on what can be sent between them is that python has to be able to "pickle" it, which means that most data (including sockets!) can be passed though.

import asyncio

from quasiqueue import QuasiQueue

async def writer(desired_items: int):
  """Feeds data to the Queue when it is low.
  """
  return xrange(0, desired_items)


async def reader(identifier: int|str):
  """Receives individual items from the queue.

  Args:
      identifier (int | str): Comes from the output of the Writer function
  """
  print(f"{identifier}")


runner = QuasiQueue(
  "hello_world",
  reader=reader,
  writer=writer,
)

asyncio.run(runner.main())

QuasiQueue has a Settings system built off of Pydantic. It's designed so multiple queues can coexist in the same codebase, and so the people deploying it can modify settings easily with Environment Variables.

I hope you find this project useful- pull requests and issues are welcome at Github, where you can also find an extensive Readme. This is the third project I've released this week, and one of my favorites- make sure to check back tomorrow for my fourth project release!

Share this:

  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on X (Opens in new window) X
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to print (Opens in new window) Print
  • More
  • Click to share on Pinterest (Opens in new window) Pinterest
  • Click to share on Tumblr (Opens in new window) Tumblr
  • Click to email a link to a friend (Opens in new window) Email

2 thoughts on “Simple Multiprocessing with QuasiQueue”

  1. Anonymous says:
    February 16, 2024 at 5:21 pm

    How would QuasiQueue work with 2 chained queues? That is:
    Producer –> Queue 1–>Consumer Tasks Group 1–>Queue 2–>Consumer Tasks Group 2 ?
    Would one make two instances of QuasiQueue and connect them somehow?

    Reply
    1. Robert Hafner says:
      May 5, 2024 at 7:37 pm

      If you were to chain queues like that you would start with one instance of a writer with a group of readers, and then each of those readers would have their own writer with it’s own readers attached. So you wouldn’t have two instances, you’d have n+1 instances of writers where N is the number of readers attached to the first process. What’s the use case for that?

      Reply

Leave a ReplyCancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

About

Robert Hafner is a Principal Engineer based in Chicago focusing on distributed applications, infrastructure, and security. This blog is a running journal of projects, tutorials, and random ideas that pop into his head.

  • GitHub
  • Mastodon
  • LinkedIn

Popular Posts

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

©2025 tedious ramblings | Built using WordPress and Responsive Blogily theme by Superb