`TypeError: el argumento 2 debe ser una conexión, un cursor o Ninguno` en Psycopg2

Tengo un oleoducto heroku configurado y acabo de habilitar las aplicaciones de revisión para él. Está utilizando el mismo código base que mis aplicaciones de preparación y producción, los mismos archivos de configuración y todo.

Cuando la aplicación de revisión se activa, puede conectarse a la base de datos creada y ejecutar migraciones. Cuando bash conectarme a la aplicación en el navegador, obtengo

`TypeError: argument 2 must be a connection, cursor or None` in `psycopg2/_json.py, register_json:139` 

La parte superior de la stack es:

 `django.contrib.sites.models._get_site_by_id`. 

He adjuntado la salida de Opbeat del marco de error al final de esta publicación.

El archivo de configuración está vinculado.

Cuando configuro DEBUG=True , todo funciona bien. ¿Qué podría sugerir un problema ALLOWED_HOSTS , pero cuando configuro ALLOWED_HOSTS en '*' con DEBUG=False , todavía hay errores?

¿Qué está mal con mi configuración? Esto funciona en la preparación y producción, pero no en las aplicaciones de revisión.

cuadro de error

tldr

 # example borked engine = sqlalchemy.create_engine('postgresql+psycopg2://', creator=lambda: 'asdf') # example works engine = sqlalchemy.create_engine('postgresql+psycopg2://', creator=lambda: conn) 

Creo que esto podría ser un error de uno de los siguientes:

  • psycopg2.extensions.register_type
  • _connect

  • Cpython

    • static PyObject *psyco_register_type
    • static PyObject * psyco_connect

ejemplos

Específicamente, el error puede surgir de:

psycopg2.

 _ipaddress.py _json.py _psycopg.cpython-37m-darwin.so _range.py extensions.py extras.py 

en mi caso:

 _ext.register_type(_ext.UUID, conn_or_curs) 

Aparentemente esto es lo que hace:

el código en mi caso que causó el problema fue create_engine keyword creator=get_connection en el siguiente ejemplo:

  from psycopg2.pool import ThreadedConnectionPool from contextlib import contextmanager import sqlalchemy conn_string = "host='127.0.0.1' dbname='postgres' user='someuser' password='somepassword'" top = ThreadedConnectionPool(1, 250, conn_string) @contextmanager def get_connection(): try: connection = top.getconn() yield connection finally: top.putconn(connection) @contextmanager def get_cursor(commit=False): with get_connection() as connection: cursor = connection.cursor( cursor_factory=psycopg2.extras.RealDictCursor) try: yield cursor if commit: connection.commit() finally: cursor.close() engine = sqlalchemy.create_engine('postgresql+psycopg2://', creator=get_connection) @contextmanager def get_sqlalchemy_engine(): yield engine.connect() 

lo que causó el problema:

 with get_sqlalchemy_engine() as engine: pd.DataFrame([1]).to_sql('asdf', engine, if_exists='replace') 

Y lo que solucionó el problema:

 @contextmanager def get_sqlalchemy_engine(): with get_connection() as conn: try: engine = sqlalchemy.create_engine('postgresql+psycopg2://', creator=lambda: conn) # engine = sqlalchemy.create_engine('postgresql+psycopg2://', creator=lambda: 'asdf') yield engine finally: engine.dispose() 

Una investigación adicional indica lo siguiente:

 JSON = new_type((oid, ), name, typecast_json) if array_oid is not None: JSONARRAY = new_array_type((array_oid, ), "%sARRAY" % name, JSON) else: JSONARRAY = None return JSON, JSONARRAY 

básicamente conn_or_curs no es una conexión o un cursor, sino otra cosa,

 register_type(JSON, not globally and conn_or_curs or None) register_type(JSONARRAY, not globally and conn_or_curs or None)