django.db.utils.InterfaceError: conexão já fechou falhas ao atualizar para o Django 3.0

10

Estou atualizando um projeto de tamanho médio para o Django 3.0 e encontrei vários erros nos meus testes depois de fazer nada além de fazer o upgrade da versão do Django da 2.3.

Todo o conjunto de testes está funcionando corretamente há anos e não foi possível encontrar nenhuma alteração relevante no log de alterações que possa apontar a causa desse problema. Aparentemente, uma única falha de teste está acionando todos os testes restantes na mesma classe TestCase para falhar, com a seguinte exceção:

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

Estou sem idéias sobre o que poderia estar acontecendo aqui.

Federico B.
fonte
2
Por favor, mostre um traço cheio pilha e uma parte de código relevante
Max Malysh
Atualizei o problema com um rastreamento de pilha mais longo. Infelizmente, não consigo identificá-lo para uma parte específica do código.
Federico B.
1
Não, todos os testes que erros são acionados connection already closedpara todos os testes restantes na classe TestCase.
Federico B.
1
Uma boa maneira de depurar esse tipo de problema é capturar o tráfego do banco de dados usando algo como tcpdump e inspecioná-lo com o Wireshark ; parece que o Postgres está fechando a conexão para que as consultas possam revelar o porquê.
Ionut Ticus 27/03
2
Notei que se você usar o TransactionTestCase para todos os testes, em vez do TestCase, isso impedirá que isso aconteça. Eu não entendo como ou por quê.
jaredkwright 29/03

Respostas:

2

Eu encontrei isso também. Parece ser um erro no pytest-django. Aqui está a questão relevante . Há um PR aberto para resolvê-lo. Se for um inconveniente grande o suficiente, você pode usar a ramificação nesse PR ou fixar suas dependências em uma versão anterior.

Schillingt
fonte
1

Apenas uma observação, é quase impossível fornecer mais informações do que as que já existem no stacktrace. No entanto, você pode investigar:

  • Verifique quando a conexão é fechada e por qual teste (execute-os individualmente via script, por exemplo).
  • Para testes que falham, verifique o código em busca de partes obsoletas do Django (procurando por itens que foram removidos / obsoletos entre 2.3 e 3.0).
  • Execute um linter para ver se alguém alterou uma variável privada dentro da estrutura do Django como solução alternativa.
  • Verifique as transações do postgres.

Depois de definir qual parte do código tem o erro, reduza-o criando testes de falha menores.

homem das cavernas
fonte
1

Estávamos enfrentando o mesmo problema e a atualização do Django 3.0.2 para o Django-3.0.4 resolveu o problema. Existem várias correções relacionadas ao banco de dados nessas duas versões, mas não sei qual resolveu o nosso problema.

bimmlerd
fonte
0

Eu tive o mesmo problema usando pytest.

O downgrade da versão 5.4.1 para a 5.3.5 foi corrigido.

P4rk
fonte
0

Todos esses problemas ocorrem devido à incompatibilidade dos outros pacotes com o django 3.0 quando corri para esse erro. Atualizei meu arquivo requirements.txt manualmente e instalei todos os requisitos usando o pip no mesmo ambiente.

raven404
fonte