如何在 'with' 语句中包装静态 class(来自 .NET)
How to wrap a static class (from .NET) in a 'with' statement
我正在尝试用漂亮的 pythonic 包装器包装一个 .NET 库,以便在 IronPython 中使用。
这个库中经常使用的模式是 PersistenceBlock,它使数据库 CRUD 操作变得干净 'all or nothing':
try:
Persistence.BeginNewTransaction()
# do stuff here
Persistence.CommitTransaction()
except Exception, e:
Persistence.AbortTransaction()
Log.Error(e)
finally:
Persistence.CloseTransaction()
我想将其包装在允许此类代码的 class 中:
with PersistenceBlock:
# do stuff here
这是我想出的:
class PersistenceBlock():
def __init__(self):
def __enter__(self):
return self
def __exit__(self, exctype, excinst, exctb):
try:
Persistence.BeginNewTransaction()
yield
Persistence.CommitTransaction()
except:
Persistence.AbortTransaction()
Log.Error(e)
finally
Persistence.CloseTransaction()
这是 PEP343 的正确实现吗?我可能会错过什么?
让我感到困惑的主要是 Persistence 是一个静态的 .NET class,因此没有 'instance' 正常意义上的管理。
我试过搜索,但是'with'这个词压倒了结果:(
您可以通过搜索 context manager
协议找到文档 - 这是应该与 with
语句一起使用的所有对象都应该实现的协议。
上下文管理器(即 __enter__
方法)不需要 return 任何东西 - 仅当您想使用 with ... as ...
语法时。在您的 __exit__
方法中,您必须进行一些适当的错误检查:如果有异常则重新引发异常,如果没有则提交。可能是这样的:
class PersistenceContext():
def __enter__(self):
# when opening the block, open a transaction
Persistence.BeginNewTransaction()
def __exit__(self, exctype, excinst, exctb):
if excinst is None:
# all went well - commit & close
Persistence.CommitTransaction()
Persistence.CloseTransaction()
else:
# something went wrong - abort, close and raise the error
Persistence.AbortTransaction()
Persistence.CloseTransaction()
raise exctype, excinst, exctb
为了完整起见,您还可以使用 contextmanager 装饰器通过一个简单的生成器来实现您的上下文:
import contextlib
@contextlib.contextmanager
def PersisenceContext():
try:
yield Persistence.BeginNewTransaction()
except Exception:
Persistence.AbortTransaction()
raise
else:
Persistence.CommitTransaction()
finally:
Persistence.CloseTransaction()
我正在尝试用漂亮的 pythonic 包装器包装一个 .NET 库,以便在 IronPython 中使用。
这个库中经常使用的模式是 PersistenceBlock,它使数据库 CRUD 操作变得干净 'all or nothing':
try:
Persistence.BeginNewTransaction()
# do stuff here
Persistence.CommitTransaction()
except Exception, e:
Persistence.AbortTransaction()
Log.Error(e)
finally:
Persistence.CloseTransaction()
我想将其包装在允许此类代码的 class 中:
with PersistenceBlock:
# do stuff here
这是我想出的:
class PersistenceBlock():
def __init__(self):
def __enter__(self):
return self
def __exit__(self, exctype, excinst, exctb):
try:
Persistence.BeginNewTransaction()
yield
Persistence.CommitTransaction()
except:
Persistence.AbortTransaction()
Log.Error(e)
finally
Persistence.CloseTransaction()
这是 PEP343 的正确实现吗?我可能会错过什么?
让我感到困惑的主要是 Persistence 是一个静态的 .NET class,因此没有 'instance' 正常意义上的管理。
我试过搜索,但是'with'这个词压倒了结果:(
您可以通过搜索 context manager
协议找到文档 - 这是应该与 with
语句一起使用的所有对象都应该实现的协议。
上下文管理器(即 __enter__
方法)不需要 return 任何东西 - 仅当您想使用 with ... as ...
语法时。在您的 __exit__
方法中,您必须进行一些适当的错误检查:如果有异常则重新引发异常,如果没有则提交。可能是这样的:
class PersistenceContext():
def __enter__(self):
# when opening the block, open a transaction
Persistence.BeginNewTransaction()
def __exit__(self, exctype, excinst, exctb):
if excinst is None:
# all went well - commit & close
Persistence.CommitTransaction()
Persistence.CloseTransaction()
else:
# something went wrong - abort, close and raise the error
Persistence.AbortTransaction()
Persistence.CloseTransaction()
raise exctype, excinst, exctb
为了完整起见,您还可以使用 contextmanager 装饰器通过一个简单的生成器来实现您的上下文:
import contextlib
@contextlib.contextmanager
def PersisenceContext():
try:
yield Persistence.BeginNewTransaction()
except Exception:
Persistence.AbortTransaction()
raise
else:
Persistence.CommitTransaction()
finally:
Persistence.CloseTransaction()