Connection Management

To open a connection to a database, use the Database.connect() method:

  1. >>> db = SqliteDatabase(':memory:') # In-memory SQLite database.
  2. >>> db.connect()
  3. True

If we try to call connect() on an already-open database, we get a OperationalError:

  1. >>> db.connect()
  2. Traceback (most recent call last):
  3. File "<stdin>", line 1, in <module>
  4. File "/home/charles/pypath/peewee.py", line 2390, in connect
  5. raise OperationalError('Connection already opened.')
  6. peewee.OperationalError: Connection already opened.

To prevent this exception from being raised, we can call connect() with an additional argument, reuse_if_open:

  1. >>> db.close() # Close connection.
  2. True
  3. >>> db.connect()
  4. True
  5. >>> db.connect(reuse_if_open=True)
  6. False

Note that the call to connect() returns False if the database connection was already open.

To close a connection, use the Database.close() method:

  1. >>> db.close()
  2. True

Calling close() on an already-closed connection will not result in an exception, but will return False:

  1. >>> db.connect() # Open connection.
  2. True
  3. >>> db.close() # Close connection.
  4. True
  5. >>> db.close() # Connection already closed, returns False.
  6. False

You can test whether the database is closed using the Database.is_closed() method:

  1. >>> db.is_closed()
  2. True

A note of caution

Although it is not necessary to explicitly connect to the database before using it, managing connections explicitly is considered a best practice. For example, if the connection fails, the exception will be caught when the connection is being opened, rather than some arbitrary time later when a query is executed. Furthermore, if you are using a connection pool, it is necessary to call connect() and close() to ensure connections are recycled properly.

Thread Safety

Peewee keeps track of the connection state using thread-local storage, making the Peewee Database object safe to use with multiple threads. Each thread will have it’s own connection, and as a result any given thread will only have a single connection open at a given time.

Context managers

The database object itself can be used as a context-manager, which opens a connection for the duration of the wrapped block of code. Additionally, a transaction is opened at the start of the wrapped block and committed before the connection is closed (unless an error occurs, in which case the transaction is rolled back).

  1. >>> db.is_closed()
  2. True
  3. >>> with db:
  4. ... print(db.is_closed()) # db is open inside context manager.
  5. ...
  6. False
  7. >>> db.is_closed() # db is closed.
  8. True

If you want to manage transactions separately, you can use the Database.connection_context() context manager.

  1. >>> with db.connection_context():
  2. ... # db connection is open.
  3. ... pass
  4. ...
  5. >>> db.is_closed() # db connection is closed.
  6. True

The connection_context() method can also be used as a decorator:

  1. @db.connection_context()
  2. def prepare_database():
  3. # DB connection will be managed by the decorator, which opens
  4. # a connection, calls function, and closes upon returning.
  5. db.create_tables(MODELS) # Create schema.
  6. load_fixture_data(db)

DB-API Connection Object

To obtain a reference to the underlying DB-API 2.0 connection, use the Database.connection() method. This method will return the currently-open connection object, if one exists, otherwise it will open a new connection.

  1. >>> db.connection()
  2. <sqlite3.Connection object at 0x7f94e9362f10>