Почему Django/Postgres, по-видимому, сохраняет, но не сохраняет, выдает «соединение уже закрыто»?

#python #django #postgresql #psycopg2 #wsl-2

Вопрос:

Я использую Django Postgres в Windows 10 WSL Ubuntu 18.04.5 LTS. Сохранение данных в postgres, похоже, работает, но когда я получаю доступ к таблице с помощью psql в командной строке, данных там нет. Обновление веб-страницы (перезагрузка Django) также показывает старые данные, предшествовавшие сохранению.

В журнале postgresql нет ошибок.

У меня нет кэширования, явно включенного в Django settings.py.

Все это отлично работало в течение многих лет, но, чтобы быть уверенным, я обновил Django до 3.2.6, Python до 3.8.11, postgresql до 12 и psycopg2 до 2.9.1, плюс необходимые зависимости. Тот же результат.

Вот код на Джанго:

     try:
        nodeToUpdate.save()  # Hit the database.
        node = Node.objects.get(pk=itemID, ofmap=mapId)  # Retrieve again to confirm it was saved
        # This shows the correct data:
        print("STORE TO MAP:"   str(node.ofmap_id)   " NODE:"   str(node.id)   " label:"   str(node.label))
    except psycopg2.InterfaceError as err:
        print(str(err))
        raise Exception(err)
    except ValidationError as err:
        raise Exception(err)
 

Ключ к пониманию того, что происходит, приходит, когда я запускаю модульные тесты:

 Traceback (most recent call last):
  File "/var/www/mysite/venv/lib/python3.8/site-packages/django/db/backends/base/base.py", line 237, in _cursor
    return self._prepare_cursor(self.create_cursor(name))
  File "/var/www/mysite/venv/lib/python3.8/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "/var/www/mysite/venv/lib/python3.8/site-packages/django/db/backends/postgresql/base.py", line 236, in create_cursor
    cursor = self.connection.cursor()
**psycopg2.InterfaceError: connection already closed**
 

Но это исключение ошибки интерфейса не поймано в коде, который я показал выше.

Я попытался установить CONN_MAX_AGE в настройках Django, но это ничего не изменило, поэтому я удалил его.

Поиск в Интернете этой ошибки привел только к появлению решений в других типах сред, как правило, несколько лет назад.

Может ли это быть связано с обновлением Windows до WSL2? В поисковых системах Google ничего не появилось.

ОБНОВЛЕНИЕ: Я только что заметил, что журналы apache исчезли (я использую «django runserver» для вышеперечисленного вместо apache, поэтому я не заметил). журналы postgres все новые с тех пор, как я начал отлаживать эту проблему. sql-дампы postgres, которые я делал в прошлом, исчезли. К счастью, мой исходный код в /var/www остается. Возможно, проблема с обновлением WSL?

Комментарии:

1. «Но это исключение ошибки интерфейса не зафиксировано в коде, который я показал выше». — > сообщается ли об этом вообще, за пределами модульных тестов?

2. @snakecharmerb Не то, что я нашел, но посмотрите обновление, которое я добавил к вопросу.

Ответ №1:

Ошибка «psycopg2.Ошибка интерфейса: соединение уже закрыто» появляется всякий раз, когда в тестируемом коде возникает ошибка, прежде чем он перейдет к проверке утверждения в тесте. По сути, это не ошибка psycopg2. По меньшей мере, неинтуитивное сообщение.

Я открыт для предложений о том, как проводить модульное тестирование в Django, в котором выявляются такие ошибки и их местоположение указывается в исходном коде, а не только в тестах. Я нашел их методом исключения: комментируя тесты и просматривая код с помощью pdb.

Мои тестовые классы все подклассы взяты из django.test.Тестовый случай, так как они запрашивают модели местами. Из документов модульного тестирования django:

Если ваши тесты зависят от доступа к базе данных, такого как создание или запрос моделей, не забудьте создать тестовые классы в качестве подклассов django.test.Тестовый, а не полный.Тестовый кейс.

Используя unittest.TestCase позволяет избежать затрат на выполнение каждого теста в транзакции и очистку базы данных, но если ваши тесты взаимодействуют с базой данных, их поведение будет отличаться в зависимости от порядка их выполнения исполнителем тестирования. Это может привести к модульным тестам, которые проходят при изолированном запуске, но завершаются неудачей при запуске в комплекте.