Après une lutte longue et brutale, je pense avoir résolu ce problème en appliquant simplement la stratégie dont les autres parlent, mais en utilisant la fonction de connexion psycopg2 elle-même :
from psycopg2 import connect
conn = connect(
database=database,
user=username,
password=password,
host=hostname,
port=port,
connect_timeout=3,
# https://www.postgresql.org/docs/9.3/libpq-connect.html
keepalives=1,
keepalives_idle=5,
keepalives_interval=2,
keepalives_count=2)
Je voyais psycopg2 se bloquer systématiquement sur des requêtes de longue durée, mais maintenant le problème semble être entièrement résolu.
Notez qu'il peut s'agir d'une nouvelle fonctionnalité, car cette question est ancienne.