O código que eu estava tentando anteriormente falha porque assume que np.Nan é seu próprio tipo quando na verdade é um float. O código a seguir, cortesia de Daniele Varrazzo em a lista de discussão psycopg2 , faz o trabalho corretamente.
def nan_to_null(f,
_NULL=psycopg2.extensions.AsIs('NULL'),
_Float=psycopg2.extensions.Float):
if not np.isnan(f):
return _Float(f)
return _NULL
psycopg2.extensions.register_adapter(float, nan_to_null)