Path: csiph.com!fu-berlin.de!uni-berlin.de!not-for-mail From: Israel Brewster Newsgroups: comp.lang.python Subject: Re: Handling transactions in Python DBI module Date: Thu, 11 Feb 2016 08:00:21 -0900 Lines: 70 Message-ID: References: <92D3C964-0323-46EE-B770-B89E7E7E6D36@ravnalaska.net> Mime-Version: 1.0 (Mac OS X Mail 9.1 \(3096.5\)) Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable X-Trace: news.uni-berlin.de Zf2meAvr5f2nOogvjkY1RQAAJNiIn+NaigZGM0QDZjTA== Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.002 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'subject:Python': 0.05; 'correspond': 0.07; 'performs': 0.07; 'api': 0.09; 'cc:addr :python-list': 0.09; 'block.': 0.09; 'cursor': 0.09; 'statements': 0.09; 'subject:module': 0.09; 'itself.': 0.11; ':-)': 0.12; 'applies': 0.15; 'subsequent': 0.15; 'thu,': 0.15; 'weird': 0.15; '"python': 0.16; "'begin": 0.16; "'not',": 0.16; '2016': 0.16; 'block),': 0.16; 'conn': 0.16; 'conn,': 0.16; 'nest': 0.16; 'personally,': 0.16; 'received:io': 0.16; 'received:psf.io': 0.16; 'statement.': 0.16; 'structure.': 0.16; 'wrote:': 0.16; 'cc:2**0': 0.20; 'cc:addr:python.org': 0.20; 'select': 0.23; 'bit': 0.23; 'feb': 0.23; 'sets': 0.23; 'second': 0.24; 'header:In-Reply-To:1': 0.24; "i've": 0.25; "doesn't": 0.26; 'chris': 0.26; 'executing': 0.27; 'tend': 0.27; 'mind,': 0.29; 'succeed': 0.29; 'objects': 0.29; 'reset': 0.29; 'starts': 0.29; '(including': 0.30; 'connection': 0.30; 'url:mailman': 0.30; 'transaction': 0.30; 'code': 0.30; 'checks': 0.30; 'query': 0.30; "i'd": 0.31; 'guess': 0.31; 'statement': 0.32; 'url:python': 0.33; 'loading': 0.33; 'url:listinfo': 0.34; 'structure': 0.34; 'next': 0.35; 'could': 0.35; 'something': 0.35; 'but': 0.36; 'should': 0.36; 'url:org': 0.36; 'possible': 0.36; 'basic': 0.36; 'pm,': 0.36; 'subject:: ': 0.37; 'received:10': 0.37; 'two': 0.37; 'being': 0.37; 'charset :us-ascii': 0.37; 'skip:p 20': 0.38; 'someone': 0.38; 'end': 0.39; 'data': 0.39; 'does': 0.39; 'rather': 0.39; 'url:mail': 0.40; 'well.': 0.40; 'easy': 0.60; 'your': 0.60; 'close': 0.61; 'header :Message-Id:1': 0.61; 'programs': 0.62; 'more': 0.63; 'different': 0.63; 'within': 0.64; 'received:10.9': 0.66; 'state,': 0.66; 'results': 0.66; 'user,': 0.67; 'therefore': 0.67; 'frank': 0.72; 'useful.': 0.72; 'received:12': 0.81; "'with'": 0.84; 'chrisa': 0.84; 'connection).': 0.84; 'sets,': 0.84 X-Warning: RFC compliance checks disabled due to whitelist X-Warning: Reverse-Path DNS check skipped due to whitelist X-Warning: Maximum message size check skipped due to whitelist X-Warning: Realtime Block Lists skipped due to whitelist X-Warning: System filters skipped due to whitelist X-Warning: Domain filters skipped due to whitelist X-Warning: User filters skipped due to whitelist X-Warning: Anti-Spam check skipped due to whitelist X-Whitelist: 2147483645 X-Envelope-From: israel@ravnalaska.net X-Envelope-To: rosuav@gmail.com In-Reply-To: X-Mailer: Apple Mail (2.3096.5) X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.21rc2 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Xref: csiph.com comp.lang.python:102816 On Feb 10, 2016, at 8:14 PM, Chris Angelico wrote: >=20 > On Thu, Feb 11, 2016 at 4:06 PM, Frank Millman = wrote: >> A connection has 2 possible states - 'in transaction', or 'not in >> transaction'. When you create the connection it starts off as 'not'. >>=20 >> When you call cur.execute(), it checks to see what state it is in. If = the >> state is 'not', it silently issues a 'BEGIN TRANSACTION' before = executing >> your statement. This applies for SELECT as well as other statements. >>=20 >> All subsequent statements form part of the transaction, until you = issue >> either conn.commit() or conn.rollback(). This performs the required = action, >> and resets the state to 'not'. >>=20 >> I learned the hard way that it is important to use conn.commit() and = not >> cur.execute('commit'). Both succeed in committing, but the second = does not >> reset the state, therefore the next statement does not trigger a = 'BEGIN', >> with possible unfortunate side-effects. >=20 > When I advise my students on basic databasing concepts, I recommend > this structure: >=20 > conn =3D psycopg2.connect(...) >=20 > with conn, conn.cursor() as cur: > cur.execute(...) And that is the structure I tend to use in my programs as well. I could, = of course, roll the transaction control into that structure. However, = that is a usage choice of the end user, whereas I am looking at the = design of the connection/cursor itself. If I use psycopg, I get the = transaction - even if I don't use a with block. >=20 > The transaction block should always start at the 'with' block and end > when it exits. As long as you never nest them (including calling other > database-using functions from inside that block), it's easy to reason > about the database units of work - they always correspond perfectly to > the code blocks. >=20 > Personally, I'd much rather the structure were "with > conn.transaction() as cur:", because I've never been able to > adequately explain what a cursor is/does. It's also a bit weird that > "with conn:" doesn't close the connection at the end (just closes the > transaction within that connection). But I guess we don't need a > "Python DB API 3.0". In my mind, cursors are simply query objects containing (potentially) = result sets - so you could have two cursors, and loop through them = something like "for result_1,result_2 in zip(cursor_1,cursor_2): ". = Personally, I've never had a need for more than one cursor, but if you = are working with large data sets, and need to work with multiple queries = simultaneously without the overhead of loading the results into memory, = I could see them being useful. Of course, someone else might have a completely different explanation = :-) >=20 > ChrisA > --=20 > https://mail.python.org/mailman/listinfo/python-list