If you're doing PostgreSQL with Python, you're almost certainly using psycopg2. It's been around since 2006, which in Python years makes it ancient, but in a good way. Federico Di Gregorio and Daniele Varrazzo built something that actually works and keeps working.
The Technical Reality
psycopg2 is basically a Python wrapper around PostgreSQL's C library (libpq). This means it's fast and doesn't do stupid things with your data, unlike pymongo or sqlite3 which are pure Python.
Thread Safety That Actually Works: You can share connections between threads without everything exploding. Don't share cursors though - that way lies madness and race conditions that will haunt your production logs. The connection-level locking means you can have multiple threads hitting the same connection without psycopg2 shitting the bed. The Python threading documentation explains the underlying concepts, and there's a good Stack Overflow discussion about database threading patterns.
Memory That Doesn't Leak: The C implementation means large result sets won't eat your server's RAM. Use server-side cursors for big queries or you'll learn about Linux's OOM killer the hard way. Watched a startup kill their prod database at 2am because they SELECT * FROM users without LIMIT and crashed the server with 10GB of user data loaded into memory. Took down their entire platform for 6 hours while they figured out why everything was fucked. The PostgreSQL memory usage docs explain the server-side implications, and here's a detailed blog post about cursor patterns that saved my bacon once.
SQL Injection Protection: Use parameterized queries or you WILL get owned. psycopg2 handles escaping properly, but it can't fix stupid. Saw a company lose 3 days worth of user uploads because they forgot to parameterize one DELETE query in an admin script. "DELETE FROM files WHERE user_id = " + user_input + ";" - yeah, that ended exactly how you'd expect when someone typed "1 OR 1=1" into the form. The OWASP SQL Injection Guide covers the attack vectors, psycopg2's query composition docs explain the right way to do it, and here's a terrifying collection of real SQL injection examples if you need motivation to fix your code.
Real-World Usage
Django uses psycopg2 as its default PostgreSQL backend, and SQLAlchemy relies on it too. This isn't marketing fluff - it means the combination has been battle-tested in production at scale. Flask-SQLAlchemy builds on this foundation, FastAPI works great with it, and Celery task queues use it for persistence. When you're debugging at 3am, you want boring, reliable tools. Here's Instagram's engineering blog talking about their PostgreSQL usage at scale.
Version 2.9.10 came out October 2024 and supports Python 3.8 through 3.12 (3.13 support is still broken as of late 2024). It handles pretty much every PostgreSQL feature you'll actually use - or at least I haven't hit any missing ones yet. The maintainers put new development into psycopg3, but psycopg2 isn't going anywhere - too much production code depends on it.