我应该如何从 with 语句返回有趣的值?
-
22-08-2019 - |
题
有没有比使用全局变量从上下文管理器获取有趣值更好的方法?
@contextmanager
def transaction():
global successCount
global errorCount
try:
yield
except:
storage.store.rollback()
errorCount += 1
else:
storage.store.commit()
successCount += 1
其他可能性:
单身人士
某种全局变量...
元组作为上下文管理器的参数
使函数更具体地解决问题/可重用性降低
保存特定属性作为上下文管理器参数的实例
与元组相同的问题,但更清晰
在保存值的上下文管理器末尾引发异常。
真是个坏主意
解决方案
看 http://docs.python.org/reference/datamodel.html#context-managers
创建一个类来保存成功和错误计数,并实现 __enter__
和 __exit__
方法。
其他提示
我仍然认为您应该创建一个类来保存错误/成功计数,正如我在您中所说的 最后一个问题. 。我猜你有自己的课程,所以只需添加这样的内容即可:
class transaction:
def __init__(self):
self.errorCount = 0
self.successCount = 0
def __enter__(*args):
pass
def __exit__(self, type, value, traceback):
if type:
storage.store.rollback()
self.errorCount += 1
else:
storage.store.commit()
self.successCount += 1
(type
如果调用后没有异常则为 None contextmanager
)
然后你可能已经在某个地方使用它了,这将调用 contextmanager
并运行你的 __exit__()
代码。 编辑: 正如 Eli 评论的那样,仅当您想要重置计数器时才创建新的事务实例。
t = transaction()
for q in queries:
with t:
t.execute(q)
“元组作为上下文管理器的参数
使函数更具体地解决问题/可重用性降低”
错误的。
这使得上下文管理器保留状态。
如果您不实现除此之外的任何内容,它将是可重用的。
但是,您实际上无法使用元组,因为它是不可变的。你需要一些可变的集合。我想到了字典和类定义。
因此,建议的实施是
“将特定属性作为上下文管理器的参数的实例”
您只需要一个具有两个属性的简单类定义。但是,您的事务状态是有状态的,您需要在某处保留状态。
class Counters(dict):
SUCCEED= 0
FAIL= 1
def __init__( self ):
self[ self.SUCCEED ]= 0
self[ self.FAIL ]= 0
def increment( self, status ):
self[status] += 1
class Transaction(object):
def __init__( self, worker, counters ):
self.worker= worker
self.counters= counters
def __enter__( self ):
self.counters.status= None
def process( self, *args, **kw ):
status= self.worker.execute( *args, **kw )
self.counters.increment( status )
def __exit__( self ):
pass
counts= Counters()
for q in queryList:
with Transaction(execQuery,counts) as t:
t.process( q )
print counts
不隶属于 StackOverflow