NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #2342 most downloaded on PyPI
Thread-safe async-aware queue for Python
Last release 9 months ago
31 Dec 2025
Release timing varies
gaps range from 9 days to 6 months
Nearly every release is documented
notes for 13 of 13 stable releases
Nothing withdrawn
no release was ever pulled
2 years old
13 releases · first in 2024
One column per month.
culsans.__version__ and culsans.__version_tuple__ as a way to retrieve the package version at runtime.
culsans.__version__ and culsans.__version_tuple__ as a way to retrieve the package version at runtime.culsans.Grouper (initial implementation) as a higher-level synchronization primitive with phase-fair priority policy by default. See x42005e1f/aiologic#19 for details.culsans.RWLock (initial implementation) as a readers-writer lock that is both phase-fair and reentrant. It is currently defined as a subclass of culsans.Grouper, but this may change in the future.culsans.BaseQueueProxy as a common superclass for culsans.SyncQueueProxy and culsans.AsyncQueueProxy. Added to reduce code duplication, but can also be used separately for other purposes (such as checking that an object is an instance of either proxy type).culsans.GreenQueue, culsans.GreenQueueProxy, and methods prefixed with green_, which make the interfaces aiologic-like. They are equivalent to their "sync" alternatives and are preferred for new uses.blocking parameter wherever there is block parameter, as its alias. This change complements the previous one. Note that none of these parameters have been added to async def methods, as this would complicate the implementation, so there is still no full compatibility with aiologic queues (the parameters will be added in the future along with async timeouts).sizer parameter, corresponding isize() public methods, and _isize protected attribute/method (for overriding). Allows to specify the size for each queue item, which affects the put methods. Solves #9.clearable() methods and related culsans.Queue._clearable() protected method (for overriding) analogous to those for peek methods, making implementation of the clear() method optional. Along with this, the clear() method is now also used in the implementation of the shutdown() method, when available.size property, which returns the cumulative size of items in the queue.green_proxy/async_proxy properties as a more generic alternative to sync_q/async_q.unfinished_tasks property is now treated as infinity (extends subclassing capabilities).__len__() and __bool__(), allowing len(queue) and bool(queue) to be used in the same sense as for collections. And while this change is not conceptually incompatible, in fact it breaks the not-so-good pattern if self.queue: # self.queue is not None.maxsize property is now defined as the maximum cumulative size of queue items rather than the maximum queue length. This allows arbitrary queue item sizes to be supported, but may require existing code to be modified to work correctly when passing a custom sizer (as this affects both the put methods and the full() methods).culsans.Queue somewhat compatible with sqlalchemy.util.queue.Queue. However, the main reason is not this, but to make the following change efficiently implemented.aiologic safety guarantees when using the condition variables. Previously, as with threading.Condition, a KeyboardInterrupt raised during synchronization on the underlying lock after notification led to the lock being over-released and, as a result, to a RuntimeError. Now, aiologic.Condition is used as a context manager, thereby including additional checks on the aiologic side to ensure that the current thread owns the lock when releasing it.unfinished_tasks property's value now changes according to the queue length change (the value returned by the _qsize() method). This allows to create flattened queues without introducing related additional methods and also corrects the behavior for subclasses that may not change the queue length as a result of insertion.timeout parameter's value is now checked and converted at the beginning of the method call, regardless of the block parameter's value. This should prevent cases where an incorrect value is passed.aiologic.meta.export() for exports instead of using its own implementation (similar to aiologic==0.15.0), which provides safer behavior. In particular, queue methods now also update their metadata, allowing them to be safely referenced during pickling.typing_extensions.Protocol on Python below 3.13, which backports all related fixes and improvements to older versions of Python.block parameter's value. Now they do not make the call in the non-blocking case.For the underlying lock, aiologic.lowlevel._thread was used, which has been declared deprecated in the latest version of aiologic .
culsans.Queue.waiting as the third aiologic-like property. Useful when you need to reliably obtain the total number of waiting ones.aiologic (support for very large numbers, additional checking for NaN, use of the clock functions from aiologic.lowlevel). This is particularly relevant for aiologic>=0.15.0, which implements safe timeouts, but has almost no impact on older versions.culsans.Queue now return proxies instead of protocols for type checkers. This allows, for example, accessing the wrapped queue via the proxy attribute without type errors.__lt__() or __gt__() method). This corresponds to recent changes in typeshed for the standard queues (see python/typeshed#14418) and makes them safer.aiologic.lowlevel._thread was used, which has been declared deprecated in the latest version of aiologic.0.9.0 regression).For asynchronous checkpoints, aiologic.lowlevel.checkpoint() was used, which has been declared deprecated in the latest version of aiologic .
setuptools to uv + hatch. It keeps the same pyproject.toml format, but has better performance, better logging, and builds cleaner source distributions (without setup.cfg)..git_archival.txt) and source distributions (via PKG-INFO).aiologic.lowlevel.checkpoint() was used, which has been declared deprecated in the latest version of aiologic.trio case by default), the get methods could lose items on cancellations, and for the put methods, it was impossible to determine whether the put was successful or not on the same cancellations (0.2.1 regression).Python 3.8 support. This makes the list of supported versions consistent with that of aiologic . Previously, the lowest supported version was 3.9.
aiologic. Previously, the lowest supported version was 3.9.culsans.MixedQueue as a queue protocol that provides both types of blocking methods via prefixes. Can be used to generalize culsans.Queue and its derivatives by type checkers, as it does not include janus.Queue-specific and other foreign methods and properties/attributes.aiologic>=0.13.0 is used (previously >=0.12.0 was used), which provides type annotations. This removes mypy-specific type ignores.For culsans.QueueShutDown on Python below 3.13, backported exceptions were defined, but they caused name conflicts for type checkers. Now, all queue s
culsans.QueueShutDown on Python below 3.13, backported exceptions were defined, but they caused name conflicts for type checkers. Now, all queue shutdown exceptions reference the same class (on Python below 3.13).culsans.QueueEmpty , culsans.QueueFull , and culsans.QueueShutDown as exceptions compatible with any interface (they inherit both types). They are now
culsans.QueueEmpty, culsans.QueueFull, and culsans.QueueShutDown as exceptions compatible with any interface (they inherit both types). They are now also raised instead of specialized exceptions, allowing any type to be used in try-catch.culsans.Queue via prefixes (sync_ and async_). The main reason for this is to move the entire implementation from the proxy classes to the queue classes. However, they can also be used as a simpler, shorter style of working with queues (similar to aiologic, but with sync_ instead of green_).culsans.Queue.putting and culsans.Queue.getting as aiologic-like properties. They can be used to obtain the number of waiting ones for a given operation type. But note, culsans.Queue.getting also includes the number of peekers.culsans.Queue now inherits from culsans.BaseQueue instead of Generic. This improves type safety and allows introspection at runtime._ prefix) to the synchronization primitives used, to better mimic the queue module.The behavior of Janus-specific methods now corresponds to janus>=2.0.0 (instead of 1.2.0 ). The only change is that after calling culsans.Queue.close(
janus>=2.0.0 (instead of 1.2.0). The only change is that after calling culsans.Queue.close(), *QueueShutDown is now raised instead of RuntimeError.culsans.Queue.aclose() method, which replicates the behavior of the same-named Janus method. This makes the interface compliant with the Janus API ver
culsans.Queue.aclose() method, which replicates the behavior of the same-named Janus method. This makes the interface compliant with the Janus API version 1.2.0 (instead of 1.1.0).peekable() methods and related culsans.Queue._peekable() protected method (for overriding). They simplify non-peekable subclass creation by providing
peekable() methods and related culsans.Queue._peekable() protected method (for overriding). They simplify non-peekable subclass creation by providing a unified contract for how to deal with it from the user's side.culsans.UnsupportedOperation exception, which is raised when attempting to call any of the peek methods for a non-peekable queue.culsans.Queue.close() and culsans.Queue.wait_closed() methods, culsans.Queue.closed property to implement compatibility with janus>=1.1.0 . For the mo
culsans.Queue.close() and culsans.Queue.wait_closed() methods, culsans.Queue.closed property to implement compatibility with janus>=1.1.0. For the most part, they behave similarly to the originals (including the exception raised after closing), but semantically they are closer to the queue shutdown methods from Python 3.13. This differs from the janus behavior, but solves aio-libs/janus#237.peek() and peek_nowait() methods, related culsans.Queue._peek() protected method (for overriding), as a way to retrieve an item from a queue without removing it. In a sense, they implement partial compatibility with the gevent queues, but peek/front is also a well-known third type of queue operation.clear() method and related culsans.Queue._clear() protected method (for overriding). Atomically clears the queue, ensuring that other threads do not affect the clearing process, and updates the unfinished_tasks property at the same time. Solves aio-libs/janus#645.Mixed use of both types of methods could lead to deadlocks (due to the use of a shared wait queue for the underlying lock). This could be considered e
culsans.Queue.maxsize can now be changed dynamically at runtime (growing & shrinking). This allows for more complex logic to be implemented, whereby t
culsans.Queue.maxsize can now be changed dynamically at runtime (growing & shrinking). This allows for more complex logic to be implemented, whereby the maximum queue size is adjusted according to certain external conditions. Related: python/cpython#54319.__dict__, thereby preventing unknown attributes from being set. This makes them safer.Janus-like mixed queues and all related API (excluding some Janus-specific methods that seem redundant on Python 3.13, in favor of new methods such as
shutdown()). They use the same patterns as the queue module, but rely on the condition variables from aiologic. This makes them 4-8 times faster than janus.Queue in multi-threaded tests, simplifies usage, and expands the number of supported use cases (multiple event loops, trio support, etc.).shutdown()). They use the same patterns as the queue module, but rely on
the condition variables from aiologic. This makes them 4-8 times faster
than janus.Queue in multi-threaded tests, simplifies usage, and expands the
number of supported use cases (multiple event loops, trio support, etc.).Your coding agent can read these notes before it upgrades. Set up the MCP server →