#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. Да, это сработало!!! Блестяще. (Это действительно легко, когда вы знаете, как.) Миллион благодарностей.