First I'd like to state I'm well aware that psycopg opens a transaction that requires to be committed for a database update to occur.
However here is a quote for the documentation regarding commit:
commit()
Commit any pending transaction to the database.
By default, Psycopg opens a transaction before executing the first command: if commit() is not called, the effect of any data manipulation will be lost.
The connection can be also set in “autocommit” mode: no transaction is automatically open, commands have immediate effect. See Transactions control for details.
Changed in version 2.5: if the connection is used in a with statement, the method is automatically called if no exception is raised in the with block.
And similarly for rollback :
rollback()
Roll back to the start of any pending transaction. Closing a connection without committing the changes first will cause an implicit rollback to be performed.
Changed in version 2.5: if the connection is used in a with statement, the method is automatically called if an exception is raised in the with block.
However this doesn't seem to work for me. Maybe I'm being picky and and should always take the habit of explicitly committing (but it would be nice to know that a rollback will occur if I forget it for example). I was wondering if someone came up with the same issue or if I'm using my with statement incorrectly.
Here is what my code looks like :
import psycopg2
from contextlib import closing
with closing(psycopg2.connect(
#conn params
) as conn, \
closing(conn.cursor()) as cur:
try:
sql = #query
cur.execute(sql)
output = cur.statusmessage
print output
except Exception, e :
print "Error message : {}".format(e)
raise
This doesn't work. There is no problem with the query itself since I get : UPDATE 842518 as output as expected. However the changes from the connection are clearly not committed since my db isn't updated. If I add
conn.commit()
in the try statement it works but the whole point is to avoid doing so.
My psycopg2 version is 2.6.
Link to doc
Thread and process safetyThe Psycopg module and the connection objects are thread-safe: many threads can access the same database either using separate sessions and creating a connection per thread or using the same connection and creating separate cursors.
All the function arguments are Psycopg extensions to the DB API 2.0. commit() Commit any pending transaction to the database. By default, Psycopg opens a transaction before executing the first command: if commit() is not called, the effect of any data manipulation will be lost.
Psycopg is the most popular PostgreSQL database adapter for the Python programming language. Its main features are the complete implementation of the Python DB API 2.0 specification and the thread safety (several threads can share the same connection).
Wrapping the connection and cursor objects in closing is prolly messing with their context handling; they are context managers them selves. A closing
wrapper will just call their close()
methods on exit.
There's no need to manually call close()
when using cursors in a with-block. The same does not apply to connections; only the transaction is ended on exit from a with-block. This is by design, so that you can use the same connection in multiple with-blocks:
Note that, unlike file objects or other resources, exiting the connection’s with block doesn’t close the connection but only the transaction associated with it: a connection can be used in more than a with statement and each with block is effectively wrapped in a separate transaction
You could for example wrap the connection in closing
in an outermost with-block, and then use the same connection in inner with-blocks for transaction handling etc:
# This'll handle closing the connection
with closing(psycopg2.connect(...)) as conn:
# This'll handle the transaction and closing the cursor
with conn, conn.cursor() as cur:
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With