Reputation: 3941
Say I have a class to create Redshift object dependencies. I want to create a single connection, and then re-use it for many different transactions.
Should I create it in the __init__
function, and then set the self.conn.close()
in the __del__
statement to mimic the with
or try/finally
model?
EDIT: Here is what I came up with:
class DatabaseConn:
def __init__(self, env: DBEnvironment = DBEnvironment.PROD):
"""
A database connection that can be safely instantiated once, and then
passed around inside a class or between functions.
:param env: The environment to connect to, choices are `DEV` and
`PROD`.
"""
self._conn = ppg2.connect(**env.value)
def __del__(self):
self._conn.close()
def execute(
self,
query_or_stmt: str,
has_res: bool = True) -> Optional[List[Tuple[Any]]]:
"""
Creates a new cursor object, and executes the query/statement. If
`has_res` is `True`, then it returns the list of tuple results.
:param query_or_stmt: The query or statement to run.
:param has_res: Whether or not results should be returned.
:return: If `has_res` is `True`, then a list of tuples.
"""
cur = self._conn.cursor()
cur.execute(query_or_stmt)
if has_res:
return cur.fetchall()
def return_cursor(self):
"""
:return: A psycopg2 cursor.
"""
return self._conn.cursor()
Upvotes: 0
Views: 2491
Reputation: 1452
I would recommend avoiding del as a destructor since it's calling pattern is nondeterministic and it is not guaranteed to be called at all.
If you want to get a with
resource as
bounded var behaviour, you can do that by using the contextlib
module.
from contextlib import contextmanager
@contextmanager
def tag(name):
print("<%s>" % name)
yield
print("</%s>" % name)
>>> with tag("h1"):
... print("foo")
...
<h1>
foo
</h1>
this example come from the python docs at: https://docs.python.org/3/library/contextlib.html
The disadvantage of this method is that the context of your resource needs to be coded.
An alternative is to write a real destructor that will be called when the connections reference counter hits 0. This is pretty similar to your original idea of using __del__
but to avoid the many of the issues with using __del__
directly, use weakref.finalize.
Upvotes: 1