django.db.utils.InterfaceError: la conexión ya cerró fallas al actualizar a Django 3.0

10

Estoy actualizando un proyecto de tamaño mediano a Django 3.0 y me encuentro con varios errores en mis pruebas después de hacer nada más que subir la versión de Django de 2.3.

Todo el conjunto de pruebas ha estado funcionando correctamente durante años y no pude encontrar ningún cambio relevante en el registro de cambios que pueda señalar la causa de este problema. Aparentemente, un solo error de prueba está provocando que todas las pruebas restantes en la misma clase TestCase fallen con la siguiente excepción:

Traceback (most recent call last):
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/db/backends/base/base.py", line 238, in _cursor
    return self._prepare_cursor(self.create_cursor(name))
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/utils/asyncio.py", line 24, in inner
    return func(*args, **kwargs)
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/db/backends/postgresql/base.py", line 231, in create_cursor
    cursor = self.connection.cursor()
psycopg2.InterfaceError: connection already closed

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/federicobond/code/forks/core/apps/participants/tests/test_views.py", line 40, in setUp
    self.client.force_login(self.user)
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/test/client.py", line 602, in force_login
    self._login(user, backend)
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/test/client.py", line 611, in _login
    if self.session:
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/test/client.py", line 461, in session
    session.save()
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/contrib/sessions/backends/db.py", line 81, in save
    return self.create()
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/contrib/sessions/backends/db.py", line 51, in create
    self._session_key = self._get_new_session_key()
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/contrib/sessions/backends/base.py", line 162, in _get_new_session_key
    if not self.exists(session_key):
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/contrib/sessions/backends/db.py", line 47, in exists
    return self.model.objects.filter(session_key=session_key).exists()
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/db/models/query.py", line 777, in exists
    return self.query.has_results(using=self.db)
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/db/models/sql/query.py", line 534, in has_results
    return compiler.has_results()
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 1107, in has_results
    return bool(self.execute_sql(SINGLE))
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 1135, in execute_sql
    cursor = self.connection.cursor()
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/utils/asyncio.py", line 24, in inner
    return func(*args, **kwargs)
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/db/backends/base/base.py", line 260, in cursor
    return self._cursor()
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/db/backends/base/base.py", line 238, in _cursor
    return self._prepare_cursor(self.create_cursor(name))
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/db/utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/db/backends/base/base.py", line 238, in _cursor
    return self._prepare_cursor(self.create_cursor(name))
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/utils/asyncio.py", line 24, in inner
    return func(*args, **kwargs)
  File "/Users/federicobond/code/forks/core/env/lib/python3.7/site-packages/django/db/backends/postgresql/base.py", line 231, in create_cursor
    cursor = self.connection.cursor()
django.db.utils.InterfaceError: connection already closed

No tengo ideas sobre lo que podría estar pasando aquí.

Federico B.
fuente
2
Muestre
Actualicé el problema con un seguimiento de pila más largo. Desafortunadamente, no puedo identificarlo en una parte específica del código.
Federico B.
1
No, cada prueba que connection already closedproduce errores se dispara para todas las pruebas restantes en la clase TestCase.
Federico B.
1
Una buena forma de depurar este tipo de problema es capturar el tráfico de la base de datos utilizando algo como tcpdump e inspeccionarlo con Wireshark ; parece que Postgres está cerrando la conexión para que las consultas revelen por qué.
Ionut Ticus
2
Noté que si usa TransactionTestCase para cada prueba en lugar de TestCase, de alguna manera evita que esto suceda. No entiendo cómo o por qué.
Jaredkwright

Respuestas:

2

Me encontré con esto también. Parece ser un error en pytest-django. Aquí está el tema relevante . Hay un RP abierto para resolverlo. Si es un inconveniente lo suficientemente grande, puede usar la rama en ese PR o anclar sus dependencias a una versión anterior.

Schillingt
fuente
1

Solo una nota de avance, es casi imposible proporcionar más información de la que ya está en el stacktrace. Sin embargo, puedes investigar:

  • Compruebe cuándo se cierra la conexión y por qué prueba (ejecútelos individualmente a través de un script, por ejemplo).
  • Para las pruebas que fallan, verifique el código de las partes en desuso de Django (buscando cosas que fueron eliminadas / en desuso entre 2.3 y 3.0).
  • Ejecute un linter para ver si alguien cambió una variable privada dentro del marco de Django como solución alternativa.
  • Consulta las transacciones de postgres.

Luego, una vez que tenga qué parte del código tiene el error, acéptelo creando pruebas de fallas más pequeñas.

Cavernícola
fuente
1

Nos encontramos con el mismo problema, y ​​la actualización de Django 3.0.2 a Django-3.0.4 lo resolvió. Hay varias correcciones relacionadas con DB en esas dos versiones, pero no sé cuál resolvió nuestro problema.

bimmlerd
fuente
0

Tuve el mismo problema usando pytest.

La degradación de 5.4.1 a 5.3.5 lo arregló.

P4rk
fuente
0

Todos estos problemas ocurren debido a la incompatibilidad de los otros paquetes con django 3.0 cuando me encontré con este error, actualicé mi archivo require.txt manualmente y luego instalé todos los requisitos usando pip en el mismo entorno.

raven404
fuente