`TypeError: argument 2 must be a connection, cursor or None` in Psycopg2

2024/10/7 12:20:58

I have a heroku pipeline set up, and have just enabled review apps for it. It is using the same codebase as my staging and production apps, same settings files and everything.

When the review app spins up, it can connect to the created DB and run migrations. When I try to connect to the app in the browser, I get

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

Top of stack is:

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

I've attached the Opbeat output of the error frame at the bottom of this post.

Settings file is linked.

When I set DEBUG=True, everything works fine. Which might suggest an ALLOWED_HOSTS issue, but when I set ALLOWED_HOSTS to '*' with DEBUG=False, it still errors?

What is wrong with my setup? This works in staging, and production, but not the review apps.

error frame

Answer

tldr

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

I think this might be an error from one of the following:

  • psycopg2.extensions.register_type

  • _connect

  • cpython

    • static PyObject *psyco_register_type
    • static PyObject * psyco_connect

examples

  • https://github.com/psycopg/psycopg2/search?q=register_type&unscoped_q=register_type

Specifcally the error can be raised from :

psycopg2.

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

in my case:

_ext.register_type(_ext.UUID, conn_or_curs)

Apparently this is what it does:

  • https://github.com/psycopg/psycopg2/blob/master/doc/src/extensions.rst#database-types-casting-functions

the code in my case which caused the issue was the create_engine keyword creator=get_connection in the following example:

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

what caused the issue:

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

And what fixed the issue:

@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 enginefinally:engine.dispose()

further research indicates the following:

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

basically conn_or_curs is not a connection or cursor, but rather some other thing,

register_type(JSON, not globally and conn_or_curs or None)
register_type(JSONARRAY, not globally and conn_or_curs or None)
  • https://github.com/psycopg/psycopg2/blob/f947c0e6be1d2c3ea8d2d8badf683b95bd213444/psycopg/psycopgmodule.c#L189
  • https://github.com/psycopg/psycopg2/blob/f947c0e6be1d2c3ea8d2d8badf683b95bd213444/psycopg/psycopgmodule.c#L260
https://en.xdnf.cn/q/70245.html

Related Q&A

replace string if length is less than x

I have a dataframe below. a = {Id: [ants, bees, cows, snakes, horses], 2nd Attempts: [10, 12, 15, 14, 0],3rd Attempts: [10, 10, 9, 11, 10]} a = pd.DataFrame(a) print (a)I want to able add text (-s) to …

Convert ast node into python object

Given an ast node that can be evaluated by itself, but is not literal enough for ast.literal_eval e.g. a list comprehensionsrc = [i**2 for i in range(10)] a = ast.parse(src)Now a.body[0] is an ast.Expr…

Keras custom loss function (elastic net)

Im try to code Elastic-Net. Its look likes:And I want to use this loss function into Keras:def nn_weather_model():ip_weather = Input(shape = (30, 38, 5))x_weather = BatchNormalization(name=weather1)(ip…

Django Models / SQLAlchemy are bloated! Any truly Pythonic DB models out there?

"Make things as simple as possible, but no simpler."Can we find the solution/s that fix the Python database world?Update: A lustdb prototype has been written by Alex Martelli - if you know a…

Fabric Sudo No Password Solution

This question is about best practices. Im running a deployment script with Fabric. My deployment user deploy needs sudo to restart services. So I am using the sudo function from fabric to run these com…

cartopy: higher resolution for great circle distance line

I am trying to plot a great circle distance between two points. I have found an in the cartopy docs (introductory_examples/01.great_circle.html):import matplotlib.pyplot as plt import cartopy.crs as cc…

Python Flask date update real-time

I am building a web app with Python Flask with JavaScript. I am a beginner of Javascript.The process I do now:In Flask Python code, 1. I get data by scrapping the web (numeric data that updates every m…

How do I force pip to install from the last commit of a branch in a repo?

I want pip to install from the latest commit on a master branch of my github repository. I tried many options mentioned here on StackOverflow, none helped. For instance, that does not work:pip install …

Emacs: pass arguments to inferior Python shell during buffer evaluation

recently I started using Emacs as a Python IDE, and it not quite intuitive... The problem I am struggling with right now is how to pass command line arguments to the inferior python shell when the buff…

How to edit a wheel package (.whl)?

I have a python wheel package, when extracted I find some python code, Id like to edit this code and re-generate the same .whl package again and test it to see the edits .. How do I do that?