2

I am working on some code that connects to an sqlite database. In the process of debugging said code, I am running into problems where I have hanging open connections to the database because some error prevented the execution of the close commands. Because db and c are defined within a function, I can't then find and close those objects from the command line. They are like orphaned connections or something, but in any case they prevent me from doing anything else with the database until I close and reopen my interactive console. Here's what it looks like:

def something()
    db=sqlite3.connect('mydatabase')
    c=db.cursor()

    somecode
    lots of different things happening in here
    this may have errors
    thus stopping execution

    db.commit()
    c.close()
    db.close()

I have tried a try/except clause with the final closing operations in a "finally" block, but that prevents exceptions from being raised back to the interactive output when I'm debugging, and things fail "silently" (maybe I'm not doing that part right?). Is there a better way to do this?

4 Answers 4

5

Generally it's good to use with...as statement:

with sqlite.connect(...) as db:
    with db.cursor() as c:
        ...

The with statement guarantees that close() will be called on an object either when with statement ends or exception is raised. And even when return or yield are called from the inside.

Read more here: http://docs.python.org/2/reference/compound_stmts.html#with

Sign up to request clarification or add additional context in comments.

3 Comments

thanks. this is simpler than the try/finally approach and seems less prone to making "silent" errors. nice and clean. cheers
Does db.cursor() actually return a context manager? I get AttributeError: __enter__ when I try the above.
This answer is wrong. with on a sqlite3.Connection only commits the statement, it does not close the connection. You need to explicitly call .close() or use contextlib.closing around .connect()
3

As pointed out by Piotr, use of the with statement makes for much more efficient code, though it does not explicitly close the connection to the database, if this is what is desired by the user. This was found by a similar question here.

What using the with statement does do is run either the con.commit() method if the code block inside the with statement is executed without error; or the con.rollback() method if an exception is encountered.

Example from http://docs.python.org/2/library/sqlite3.html

import sqlite3

con = sqlite3.connect(":memory:")
con.execute("create table person (id integer primary key, firstname varchar unique)")

with con:
    con.execute("insert into person(firstname) values (?)", ("Joe",))

# If Successful, con.commit() is called automatically afterwards
# else con.rollback() is called after the with block finishes with an exception, 
# the exception is still raised and must be caught

try:
    with con:
        con.execute("insert into person(firstname) values (?)", ("Joe",))
except sqlite3.IntegrityError:
    print "couldn't add Joe twice"

Note the use of the shortcut method con.execute() which is a method of the database connection object. This implicitly creates the cursor object for you and returns the result, and so requires even less code to be written.

Comments

0

To clean up resources, use only finally:

db = sqlite.connect(...)
try:
    ...
    c = db.cursor()
    try:
        ...
    finally:
        c.close()
    ...
finally:
    db.close()

1 Comment

i think this would work, but the with...as... approach seems better. and i think i am still having problems with how i do try/except/finally because i keep getting those silent errors. thanks though
0

In order to correct the other answers, the sqlite3.Connection object does not provide a closing context manager. It functions as a shortcut to commit any changes to the data. If you want to automatically close the connection, you want to

  1. Use a try/finally block with conn.close()

  2. Wrap your conn with contextlib.closing()

This information is now explicitly referenced in the documentation:

https://docs.python.org/3/library/sqlite3.html#sqlite3-connection-context-manager

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.