Python подключается к PostgreSQL с помощью psycopg2 — Зачем нужно закрывать и повторно открывать соединение, чтобы следующий код работал?

#python #postgresql #database-connection #psycopg2

#python #postgresql #подключение к базе данных #psycopg2

Вопрос:

Я столкнулся с загадкой при использовании psycopg2:

  • Моя программа нормально подключается и создает курсор OK
  • Этот курсор используется в «try … кроме» конструкций для удаления двух временных таблиц, если они существуют
  • (Логика ‘except’ выполняется для обоих из них, потому что таблиц не существует.)
  • Однако остальная часть программы, которая следует, завершается сбоем при первом ‘.execute ()’, потому что она не может использовать новый курсор, который, казалось, был создан НОРМАЛЬНО из этого соединения.
  • Если я закрою соединение и снова открою его (или создам и использую второе соединение), последующая логика работает нормально.
  • (Если я закомментирую оба «попробуйте… за исключением » конструкций, он работает нормально, до конца — понятно.)

Вот программный код:

 import psycopg2             # PostgreSQL module - need to install.  See https://www.psycopg.org/docs/

lcConnectionString = "...obfuscated..."

loConnection = psycopg2.connect(lcConnectionString)
print(f"loConnection after '.connect()' is: {loConnection}")

loCursor = loConnection.cursor()
print(f"loCursor is {loCursor}")

try:
    loCursor.execute("drop table TmpJobs")
    print("Dropped TmpJobs table")
except Exception as exc:
    print("Did not need to drop TmpJobs table table")

try:
    loCursor.execute("drop table TmpSubset")
    print("Dropped TmpSubset table")
except Exception as exc:
    print("Did not need to drop TmpSubset table")

print(f"loConnection after 'exceptions' is: {loConnection}")
print(f"loCursor after 'exceptions' is {loCursor}")

# The rest of the program runs fine if close and reopen the connection. But crashes if don't.
llCloseAndReopen = False            # Testing: True / False
if llCloseAndReopen:
   loConnection.close()
   print(f"loConnection after '.close()' is: {loConnection}")
   loConnection = loCursor = None
   loConnection = psycopg2.connect(lcConnectionString)
   print(f"loConnection after 're-connect' is: {loConnection}")

print("n-----------------------------------------nSelecting from Jobs into subset result...")
loCursor2 = loConnection.cursor()
print(f"loCursor2 (just created): {loCursor2}")

loCursor2.execute(f"create temporary table TmpSubset as select * from Jobs where RowID % 100 = 0")

loCursor2.execute(f"select * from TmpSubset")
loResult = loCursor2.fetchall() 
print(f"{len(loCursor2.description)} columns in Subset result")
lnRowCount = 0
for Row in loResult:
    lnRowCount  = 1
    print(f"{lnRowCount}: {Row[0]}, {Row[1]}, {Row[2]}, {Row[3]}")
print(f"{lnRowCount} rows in Subset result")
  

Если соединение не закрыто и не открыто повторно, в строке генерируется исключение:

 loCursor2.execute(f"create temporary table TmpSubset as select * from Jobs where RowID % 100 = 0")
  

Добавлено 19 ноября по запросу:
Вот последняя часть окна вывода Visual Studio 2019, в котором отображаются последние инструкции печати, сообщение об исключении и трассировка стека:

 Did not need to drop TmpSubset table
loConnection after 'exceptions' is: <connection object at 0x0579D878; dsn: 'user= ...obfuscated... host=localhost', closed: 0>
loCursor after 'exceptions' is <cursor object at 0x04815028; closed: 0>

-----------------------------------------
Selecting from Jobs into subset result...
loCursor2 (just created): <cursor object at 0x047B2F28; closed: 0>
current transaction is aborted, commands ignored until end of transaction block

Stack trace:
 >  File "J:PythonApplicationsSpeedTestTestPostgreSQLPurePython2.py", line 49, in <module>
 >    loCursor2.execute(f"create temporary table TmpSubset as select * from Jobs where RowID % 100 = 0")
  

Почему Python / psycopg2 не может использовать этот новый курсор (loCursor2) в исходном соединении после срабатывания «исключений»?
Есть идеи?

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

1. Что вы подразумеваете под сбоями при первом ‘.execute ()’ ? Есть ли какие-либо сообщения об ошибках?

2. Соединения Postgres становятся непригодными для использования после определенных типов ошибок — обычно об этом упоминается в сообщении об ошибке. Но в этом случае мы не можем точно сказать, пока вы не покажете нам сообщения об ошибках.

3. Я добавил эту дополнительную информацию для вас по запросу. К сожалению, это мало что добавляет, кроме подтверждения того, что исключение генерируется в этой первой строке ‘loCursor2.execute (…)’ (которая выполняется отлично, если я устанавливаю «llCloseAndReopen = True».

Ответ №1:

Вы должны прочитать сообщения об ошибках, которые вы получаете:

sycopg2.ошибки.InFailedSqlTransaction: текущая транзакция прервана, команды игнорируются до конца блока транзакции

Как только вы получили сообщение об ошибке, вам необходимо завершить транзакцию (откат), прежде чем вы сможете продолжить, поэтому добавьте это в свои блоки исключений.

 loConnection.rollback()
  

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

1. Да, это сработало!!! Блестяще. (Это действительно легко, когда вы знаете, как.) Миллион благодарностей.