Connection Management
To open a connection to a database, use the Database.connect()
method:
>>> db = SqliteDatabase(':memory:') # In-memory SQLite database.
>>> db.connect()
True
If we try to call connect()
on an already-open database, we get a OperationalError
:
>>> db.connect()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/charles/pypath/peewee.py", line 2390, in connect
raise OperationalError('Connection already opened.')
peewee.OperationalError: Connection already opened.
To prevent this exception from being raised, we can call connect()
with an additional argument, reuse_if_open
:
>>> db.close() # Close connection.
True
>>> db.connect()
True
>>> db.connect(reuse_if_open=True)
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:
>>> db.close()
True
Calling close()
on an already-closed connection will not result in an exception, but will return False
:
>>> db.connect() # Open connection.
True
>>> db.close() # Close connection.
True
>>> db.close() # Connection already closed, returns False.
False
You can test whether the database is closed using the Database.is_closed()
method:
>>> db.is_closed()
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).
>>> db.is_closed()
True
>>> with db:
... print(db.is_closed()) # db is open inside context manager.
...
False
>>> db.is_closed() # db is closed.
True
If you want to manage transactions separately, you can use the Database.connection_context()
context manager.
>>> with db.connection_context():
... # db connection is open.
... pass
...
>>> db.is_closed() # db connection is closed.
True
The connection_context()
method can also be used as a decorator:
@db.connection_context()
def prepare_database():
# DB connection will be managed by the decorator, which opens
# a connection, calls function, and closes upon returning.
db.create_tables(MODELS) # Create schema.
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.
>>> db.connection()
<sqlite3.Connection object at 0x7f94e9362f10>