psycogreen
Wait-callback adapters that let psycopg2 run asynchronously under gevent or eventlet coroutine event loops.
Repository Health
Technical Analysis
psycogreen is a small integration library that lets psycopg2 cooperate with coroutine-based concurrency frameworks. Psycopg2’s C extension can’t be monkey-patched directly, but it exposes a wait-callback hook that fires whenever a libpq call would block — psycogreen implements that hook for gevent and eventlet, so ordinary blocking-style psycopg2 code can run non-blocking inside a green-thread event loop without any application-code changes.
The package ships two independent modules, psycogreen.gevent and psycogreen.eventlet, each exposing a patch_psycopg() call that registers the appropriate wait callback via psycopg2.extensions.set_wait_callback(). It is intentionally minimal, with no dependencies beyond the coroutine library it targets, and is aimed at psycopg2 users on Python 2 or 3 — Psycopg 3 has gevent support built in and does not need this package.
What You Get
- Gevent wait callback -
psycogreen.gevent.patch_psycopg()registers a callback that polls the connection and yields to gevent’swait_read/wait_writeinstead of blocking. - Eventlet wait callback -
psycogreen.eventlet.patch_psycopg()registers a callback that polls the connection and yields via eventlet’strampoline(). - Zero-config integration - one function call patches psycopg2 process-wide; no changes needed to existing query code.
- Reference test scripts -
tests/test_gevent.pyandtests/test_eventlet.pydemonstrate concurrent downloads overlapping DB queries against a bundledwait_server.py.
Common Use Cases
- Green-threaded web workers - gevent- or eventlet-based WSGI servers (e.g. gunicorn gevent workers) that use psycopg2 and need DB calls to not block other greenlets.
- High-concurrency connection pooling - apps holding many concurrent psycopg2 connections where blocking libpq calls would otherwise serialize an event loop.
- Legacy Python 2/3 codebases on psycopg2 - projects that cannot move to Psycopg 3 (which has native gevent support) but still want cooperative I/O.
- Mixed I/O workloads - services that interleave HTTP requests and DB queries and want both to overlap under a single-threaded coroutine scheduler.
Under The Hood
Architecture
The package is two flat, independent modules — psycogreen/gevent.py and psycogreen/eventlet.py — each exposing a patch_psycopg() entry point and a *_wait_callback(conn, timeout) function that loops on conn.poll() and delegates the wait to its coroutine library’s socket-wait primitive (gevent.socket.wait_read/wait_write versus eventlet.hubs.trampoline). There is no shared base or abstraction layer between the two backends — the poll loop is duplicated across both files — which keeps each module importable without pulling in the other coroutine library’s dependencies, but means the two implementations could drift if psycopg2.extensions.set_wait_callback’s contract ever changed.
Tech Stack
Packaging uses a legacy setup.py/setuptools flow rather than a modern PEP 517 build backend (the pyproject.toml only carries Black configuration). The runtime dependency is psycopg2 plus whichever of gevent or eventlet the calling application has installed, imported directly at module scope. The test fixtures pull in six for Python 2/3 compatibility and a small wsgiref-based wait_server.py to simulate blocking I/O, with tox.ini/tools/flake8/tools/black wrapper scripts standing in for CI-grade linting.
Code Quality
There is no automated assertion-based test suite: the two scripts under tests/ are manual demonstration programs that require a live PostgreSQL connection and the bundled HTTP server, and they log output rather than assert correctness. No type hints are present, consistent with the project’s Python 2/3-compatible era, though error handling is explicit and narrow (ImportError when set_wait_callback is unavailable, OperationalError on an unexpected poll state). Naming is consistent and functions carry clear docstrings; flake8 and Black wrapper scripts show some lint/format discipline, but there is no visible CI workflow enforcing them.
API Design
The public surface is extremely small and symmetric: one patch_psycopg() call per backend module, mirrored function names (gevent_wait_callback/eventlet_wait_callback), and no implicit monkeypatching — the caller opts in explicitly. Getting started requires a single import plus a single function call, and each function’s docstring states exactly what it does, making the developer experience unusually low-friction for such a narrowly scoped integration shim.
Used by 2 apps in this directory
Dify
No Code Platforms · AI Development · Developer Tools
Visual LLM workflow platform with RAG pipelines, agent capabilities, and model management for building production AI applications.
knowhere
AI Development · Developer Tools
Transform messy, unstructured documents into persistent, navigable memory that AI agents can actually use.