Tracking down improperly closed database connections in an existing project can be quite challenging. Here is my approach, which I offer as a reference for those encountering the same issue:
Implementing with Python 2.7, I inspect the database connection during the destruction of a Peewee Model. If the connection remains open, a warning is issued along with the traceback; however, scenarios within the with database:
context are bypassed.
from playhouse.pool import PooledMySQLDatabase
from peewee import Model
import logging
import traceback
logger = logging.getLogger(__name__)
class TrackingDatabase(PooledMySQLDatabase):
def __init__(self, *args, **kwargs):
super(TrackingDatabase, self).__init__(*args, **kwargs)
self._in_context = False
def __enter__(self):
self._in_context = True
return super(TrackingDatabase, self).__enter__()
def __exit__(self, exc_type, exc_val, exc_tb):
self._in_context = False
return super(TrackingDatabase, self).__exit__(exc_type, exc_val, exc_tb)
@property
def in_context(self):
return self._in_context
database = TrackingDatabase(....)
class BaseModel(Model):
class Meta:
database = database
def __del__(self):
if not database.is_closed() and not database.in_context:
stack = "".join(traceback.format_stack())
logger.warning("Database connection remains open.\n%s", stack)
Then wrap the warning part in a with database:
context to ensure the connection is closed properly.