Default scope of variables

Frank Millman frank at chagford.com
Tue Jul 9 03:35:34 EDT 2013


"Chris Angelico" <rosuav at gmail.com> wrote in message 
news:CAPTjJmqkmFd4-Jpugr-vubuB6riBV6K_Mwnxc_U3CVaBr_Wgbg at mail.gmail.com...
> On Tue, Jul 9, 2013 at 4:08 PM, alex23 <wuwei23 at gmail.com> wrote:
>> On 9/07/2013 3:07 PM, Chris Angelico wrote:
>>>>>> The subtransactions are NOT concepted as separate transactions. They
>>> are effectively the database equivalent of a try/except block.
>>>>>> Sorry, I assumed each nested query was somehow related to the prior
>> one. In which case, I'd probably go with Ethan's suggestion of a
>> top-level transaction context manager with its own substransaction
>> method.
>> Yeah, that would probably be the best option in this particular
> instance. Though I do still like the ability to have variables shadow
> each other, even if there's a way around one particular piece of code
> that uses the technique.
>
I have been following this sub-thread with interest, as it resonates with 
what I am doing in my project.
In my case, one update can trigger another, which can trigger another, etc. 
It is important that they are treated as a single transaction. Each object 
has its own 'save' method, so there is not one place where all updates are 
executed, and I found it tricky to control.
I came up with the following context manager -
class DbSession:
 """
 A context manager to handle database activity.
 """
 def __init__(self):
 self.conn = None
 self.no_connections = 0
 self.transaction_active = False
 def __enter__(self):
 if self.conn is None:
 self.conn = _get_connection() # get connection from pool
 self.conn.cur = self.conn.cursor()
 # all updates in same transaction use same timestamp
 self.conn.timestamp = datetime.now()
 self.no_connections += 1
 return self.conn
 def __exit__(self, type, exc, tb):
 if type is not None: # an exception occurred
 if self.transaction_active:
 self.conn.rollback()
 self.transaction_active = False
 self.conn.release() # return connection to pool
 self.conn = None
 return # will reraise exception
 self.no_connections -= 1
 if not self.no_connections:
 if self.transaction_active:
 self.conn.commit()
 self.transaction_active = False
 self.conn.cur.close()
 self.conn.release() # return connection to pool
 self.conn = None
All objects created within a session share a common DbSession instance.
When any of them need any database access, whether for reading or for 
updating, they execute the following -
 with db_session as conn:
 conn.transaction_active = True # this line must be added if 
updating
 conn.cur.execute(__whatever__)
Now it 'just works'. I don't have the need for save-points - either all 
updates happen, or none of them do.
Frank Millman


More information about the Python-list mailing list

AltStyle によって変換されたページ (->オリジナル) /