nit*_*red 2 python refactoring
我有一个连接到数据库并获取一些数据并返回此数据的函数.除了finally块之外,整个过程都被try包围.在finally块中,即使出现错误,我也会释放资源.那么执行以下操作的pythonic方法是什么:
def fetch_data():
db_conn = None
try:
db_conn = DBConnection()
data = db_conn.get_data()
except Exception as ex:
print(f"Exception occurred when fetching data: {ex}")
finally:
if db_conn:
db_conn.close()
Run Code Online (Sandbox Code Playgroud)
初始化db_conn = None和finally块看起来不够优雅或pythonic,我想知道是否有更好的方法这样做?
您想使用上下文管理器.with语言管理器和语句被专门添加到语言中以处理此模式.
代码将变为:
with DBConnection() as db_conn:
data = db_conn.get_data()
Run Code Online (Sandbox Code Playgroud)
请参阅语句上下文管理器.的实施DBConnection将需要提供__enter__和__exit__方法来处理这个问题:
class DBConnection:
def __init__(self):
# .. initialisation of the instance. **Not** in the context manager
def close(self):
# ...
def get_data(self):
# ...
return data_loaded
def __enter__(self):
# context is entered, `try:` 'opens' *after* this point.
# Perhaps you want to actually connect to the database here
# whatever is returned here is assignable via `with ... as name`
# this can be a new object or self
return self
def __exit__(self, exc_type, exc_value, traceback):
# The context is exiting, equivalent of except ... and finally ...
self.close()
if exc_type:
print(f"Exception occurred when fetching data: {exc_value}")
# returning None will allow exceptions to propagate, returning
# True (or other true value) will clear the exception.
return True # exception is cleared
Run Code Online (Sandbox Code Playgroud)
我return self在__enter__处理程序中使用,因为这是一个很好的模式,可用于适合您特定示例的上下文管理器,但您也可以返回其他内容.例如,某些数据库适配器在该点返回事务对象或游标.
请注意,引发的__enter__异常不是上下文的一部分,不在那里处理!如果您需要在打开不想传播的数据库时处理异常,则必须推迟连接直到第一次get_data()调用.
上下文管理器封装了try: ... except ...: finally: ...模式.另请参阅PEP 343 - 将*添加到Python 的*with*语句提议:
这个PEP在Python语言中添加了一个新的"with"语句,可以分解try/finally语句的标准用法.
请注意,由您处理异常的位置取决于您的用例.对于某些上下文管理器而言__exit__,对于其他人来说,只有清理上下文而不是抑制异常才有用.例如,文件是上下文管理器,但它们不会清除异常.那时你要添加一个try: .. except SpecificException:来处理这种情况:
try:
with open(filename) as fobj:
# ...
except IOError:
# oops, file failed to open
Run Code Online (Sandbox Code Playgroud)
要么
try:
open_file = open(filename)
except IOError:
# oops, file failed to open
else:
with open_file as fobj:
# ...
Run Code Online (Sandbox Code Playgroud)
上下文管理器的目的是确保文件对象在打开时关闭,而不是其他任何东西.
| 归档时间: |
|
| 查看次数: |
46 次 |
| 最近记录: |