在以下Database类中,如果连接失败,则会打印出错误。但是,还会打印系统错误,因为__exit__
代码会触发。
AttributeError:'Database'对象没有属性'_conn'
我应该如何处理这种情况?
try/except
还是有更好的方法吗?
import psycopg2
import mysecrets as ms
from time import time
class Database(object):
def __init__(self, localhost=False):
try:
print(f"ATTEMPTING DATABASE CONNECTION")
self._conn = psycopg2.connect(
f"""
dbname = {ms.LOCALDB_NAME if localhost else ms.DB_NAME}
port = {ms.LOCALDB_PORT if localhost else ms.DB_PORT}
user = {ms.LOCALDB_USER if localhost else ms.DB_USER}
password = {ms.LOCALDB_PASS if localhost else ms.DB_PASS}
host = {ms.LOCALDB_HOST if localhost else ms.DB_HOST}
"""
)
self._cursor = self._conn.cursor()
print(f"CONNECTED TO DATABASE\n")
except Exception as error:
print(f"UNABLE TO CONNECT TO DATABASE\n{error}")
def __enter__(self):
return self
def __del__(self):
self.connection.close()
def __exit__(self, exc_type, exc_value, traceback):
self.connection.close()
@property
def connection(self):
return self._conn
@property
def cursor(self):
return self._cursor
def commit(self):
self.connection.commit()
def query(self, sql, params=None):
self.cursor.execute(sql, params or ())
def fetchall(self):
return self.cursor.fetchall()
def fetchone(self):
return self.cursor.fetchone()
if __name__ == "__main__":
start_time = time()
with Database() as db:
elapsed_time = round(time() - start_time, 2)
print(f"Testing database connection took {elapsed_time} seconds.")
在这种情况下,您可以在self._conn
之前首先初始化try
,作为self._conn = None
,这使它存在。然后,在__exit__
,close
等保护它
if self._conn is not None:
self._conn.close()
self._conn = None
但是,我不认为这是一个很好的设计捕获并忽略一般Exception
错误。它可能不是连接错误。即使它是,你最终得到一个未初始化的对象。这没用,会导致以后的错误。最好早点抓住它们,让它只是从__init__
传递出来,并让任何实例化它处理它。
首先,捕捉Exception
而不是特定的错误是反模式。在Python中,您应该知道从函数中抛出哪些异常并相应地处理它们。
其次,如果你对psycopg2.connect
或_conn.cursor()
的调用抛出任何错误,那么你的代码会捕获异常,你的实例变量_conn
和_cursor
永远不会被设置。这是你的AttributeError
的原因。
IMO,处理它的正确方法是引发错误,如果数据库类无法连接到数据库或者让任何代码使用此类处理错误,则不会继续执行。
class Database(object):
def __init__(self, localhost=False):
try:
print(f"ATTEMPTING DATABASE CONNECTION")
self._conn = psycopg2.connect(
f"""
dbname = {ms.LOCALDB_NAME if localhost else ms.DB_NAME}
port = {ms.LOCALDB_PORT if localhost else ms.DB_PORT}
user = {ms.LOCALDB_USER if localhost else ms.DB_USER}
password = {ms.LOCALDB_PASSWORD if localhost else ms.DB_PASSWORD}
host = {ms.LOCALDB_HOST if localhost else ms.DB_HOST}
"""
)
self._cursor = self._conn.cursor()
print(f"CONNECTED TO DATABASE\n")
except psycopg2.Error as error:
raise ValueError(f"UNABLE TO CONNECT TO DATABASE\n{error}") from None
可能有一个比ValueError
更好的例外。