Недавно мне понадобилось сходить в PostgreSQL из скрипта на Python . Была предпринята попытка воспользоваться для этого библиотекой py-postgresql , поскольку я успешно использовал ее в прошлом. Но оказалось, что py-postgresql не работает с последними версиями постгреса. В моем случае использовался PostgreSQL 11. Ну что же, тогда не будем выпендриваться, и возьмем используемый всеми psycopg2. Поскольку интерфейс psycopg2 заметно отличается от интерфейса py-postgresql, было решено написать небольшую памятку по использованию данной библиотеки.
Как обычно в мире Python, библиотека устанавливается через pip и при желании изолируется от других проектов с помощью virtualenv :
В MacOS вполне достаточно этой одной команды. В Linux может потребоваться вручную подтянуть библиотеку libpq , поскольку psycopg2 построен на ее базе:
Соединение с СУБД осуществляется так:
conn = psycopg2. connect ( database = «mydb» , user = «afiskon» ,
password = «s3cr3t» , host = «localhost» , port = 5432 )
Иногда бывает полезно узнать используемую версию libpq. Она доступна через переменную psycopg2.__libpq_version__
. Переменная содержит число вроде 11002 (libpq 11.2) или 90613 (libpq 9.6.13).
Взаимодействие с базой осуществляется при помощи отдельного класса, cursor:
Пример создания таблицы:
«login VARCHAR(64), password VARCHAR(64))» )
conn. commit ( )
Заметьте, что коммит транзакции осуществляется через класс connection, а не cursor.
Пример заполнения таблицы:
( «afiskon» , «123» ) )
cur. execute ( «INSERT INTO users (login, password) VALUES (%s, %s)» ,
( «eax» , «456» ) )
conn. commit ( )
То же самое, но через prepared statements :
«INSERT INTO users (login, password) VALUES ($1, $2)» )
cur. execute ( «EXECUTE insuser(%s, %s)» , ( «afiskon» , «123» ) )
cur. execute ( «EXECUTE insuser(%s, %s)» , ( «eax» , «456» ) )
conn. commit ( )
Пример SELECT-запроса:
cur. fetchall ( )
# [(1, ‘afiskon’, ‘123’), (2, ‘eax’, ‘456’)]
Можно читать и по одному картежу:
cur. fetchone ( )
# (1, ‘afiskon’, ‘123’)
cur. fetchone ( )
# (2, ‘eax’, ‘456’)
cur. fetchone ( ) is None
# True
Также класс cursor может быть использован в цилке for:
for row in cur:
print ( row )
# (1, ‘afiskon’, ‘123’)
# (2, ‘eax’, ‘456’)
Параметрам запроса можно присваивать имена. Например, как в этом UPDATE-запросе:
«login = %(login)s» , { «login» : «eax» , «password» : «789» } )
conn. commit ( )
На плейсхолдерах значений всегда должно стоять %s
, даже если передается целое число или иной тип. Например, как в следующем DELETE-запросе:
conn. commit ( )
Заметьте, что методу execute передается картеж из одного элемента. Если передать просто один аргумент без картежа, метод взорвется с ошибкой:
Пример вызова хранимки:
cur. fetchall ( )
# [(‘PostgreSQL 11.5 (Ubuntu …трали-вали три педали’,)]
По завершении работы с курсором его следует закрыть:
Чтобы постоянно не думать про все эти conn.commit()
и cur.close()
, лучше выполнять транзакции в with-блоках:
with conn. cursor ( ) as cur:
cur. execute ( «INSERT INTO users (login, password) » +
«VALUES (%s, %s)» , ( «r2auk» , «789» ) )
Заметьте, что conn также должен быть взят в with. Если во время исполнения кода не будет брошено исключение, транзакция закоммитится. Иначе она откатится. Так или иначе, все ресурсы, выделенные под cursor, будут освобождены. Соединение с СУБД остается открытым.
Чтобы явно откатить транзакцию, используйте метод rollback класса connection:
with conn. cursor ( ) as cur:
cur. execute ( «DELETE FROM users» )
conn. rollback ( )
Чтобы закрыть соединение с СУБД, используйте метод close:
try :
# работаем с базой
finally :
conn. close ( )
Конечно же, описать абсолютно все нюансы работы c psycopg2 в рамках одного поста не представляется возможным. Дополнительные сведения вы найдете в официальной документации .