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

Using autoconnect

It is not necessary to explicitly connect to the database before using it if the database is initialized with autoconnect=True (the default). Managing connections explicitly is considered a best practice, therefore you may consider disabling the autoconnect behavior.

It is very helpful to be explicit about your connection lifetimes. If the connection fails, for instance, the exception will be caught when the connection is being opened, rather than some arbitrary time later when a query is executed. Furthermore, if using a connection pool, it is necessary to call connect() and close() to ensure connections are recycled properly.

For the best guarantee of correctness, disable autoconnect:

  1. db = PostgresqlDatabase('my_app', user='postgres', autoconnect=False)

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>