Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

use try/except with psycopg2 or "with closing"?

Tags:

I'm using Psycopg2 in Python to access a PostgreSQL database. I'm curious if it's safe to use the with closing() pattern to create and use a cursor, or if I should use an explicit try/except wrapped around the query. My question is concerning inserting or updating, and transactions.

As I understand it, all Psycopg2 queries occur within a transaction, and it's up to calling code to commit or rollback the transaction. If within a with closing(... block an error occurs, is a rollback issued? In older versions of Psycopg2, a rollback was explicitly issued on close() but this is not the case anymore (see http://initd.org/psycopg/docs/connection.html#connection.close).

My question might make more sense with an example. Here's an example using with closing(...

with closing(db.cursor()) as cursor:      cursor.execute("""UPDATE users                                  SET password = %s, salt = %s              WHERE user_id = %s""",              (pw_tuple[0], pw_tuple[1], user_id))      module.rase_unexpected_error()      cursor.commit() 

What happens when module.raise_unexpected_error() raises its error? Is the transaction rolled back? As I understand transactions, I either need to commit them or roll them back. So in this case, what happens?

Alternately I could write my query like this:

cursor = None try:     cursor = db.cursor()     cursor.execute("""UPDATE users                                 SET password = %s, salt = %s             WHERE user_id = %s""",             (pw_tuple[0], pw_tuple[1], user_id))     module.rase_unexpected_error()     cursor.commit() except BaseException:     if cursor is not None:         cursor.rollback() finally:     if cursor is not None:         cursor.close() 

Also I should mention that I have no idea if Psycopg2's connection class cursor() method could raise an error or not (the documentation doesn't say) so better safe than sorry, no?

Which method of issuing a query and managing a transaction should I use?

like image 586
skyler Avatar asked Sep 26 '12 18:09

skyler


People also ask

Is psycopg2 asynchronous?

Asynchronous notificationsPsycopg allows asynchronous interaction with other database sessions using the facilities offered by PostgreSQL commands LISTEN and NOTIFY.

Is psycopg2 connection thread-safe?

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.

What is the difference between SQLAlchemy and psycopg2?

The psycopg2 is over 2x faster than SQLAlchemy on small table. This behavior is expected as psycopg2 is a database driver for postgresql while SQLAlchemy is general ORM library.

Does psycopg2 need PostgreSQL?

The psycopg2-binary package is meant for beginners to start playing with Python and PostgreSQL without the need to meet the build requirements.


1 Answers

Your link to the Psycopg2 docs kind of explains it itself, no?

... Note that closing a connection without committing the changes first will cause any pending change to be discarded as if a ROLLBACK was performed (unless a different isolation level has been selected: see set_isolation_level()).

Changed in version 2.2: previously an explicit ROLLBACK was issued by Psycopg on close(). The command could have been sent to the backend at an inappropriate time, so Psycopg currently relies on the backend to implicitly discard uncommitted changes. Some middleware are known to behave incorrectly though when the connection is closed during a transaction (when status is STATUS_IN_TRANSACTION), e.g. PgBouncer reports an unclean server and discards the connection. To avoid this problem you can ensure to terminate the transaction with a commit()/rollback() before closing.

So, unless you're using a different isolation level, or using PgBouncer, your first example should work fine. However, if you desire some finer-grained control over exactly what happens during a transaction, then the try/except method might be best, since it parallels the database transaction state itself.

like image 192
voithos Avatar answered Sep 29 '22 17:09

voithos