gpt4 book ai didi

python - 检测上下文管理器嵌套

转载 作者:太空宇宙 更新时间:2023-11-03 13:10:26 24 4
gpt4 key购买 nike

最近想知道有没有办法检测上下文管理器是否嵌套。

我已经创建了 Timer 和 TimerGroup 类:

class Timer:
def __init__(self, name="Timer"):
self.name = name
self.start_time = clock()

@staticmethod
def seconds_to_str(t):
return str(timedelta(seconds=t))

def end(self):
return clock() - self.start_time

def print(self, t):
print(("{0:<" + str(line_width - 18) + "} >> {1}").format(self.name, self.seconds_to_str(t)))

def __enter__(self):
return self

def __exit__(self, exc_type, value, traceback):
self.print(self.end())


class TimerGroup(Timer):
def __enter__(self):
print(('= ' + self.name + ' ').ljust(line_width, '='))
return self

def __exit__(self, exc_type, exc_val, exc_tb):
total_time = self.seconds_to_str(self.end())
print(" Total: {0}".format(total_time).rjust(line_width, '='))
print()

此代码以可读格式打印时间:

with TimerGroup("Collecting child documents for %s context" % context_name):
with Timer("Collecting context features"):
# some code...
with Timer("Collecting child documents"):
# some code...


= Collecting child documents for Global context ============
Collecting context features >> 0:00:00.001063
Collecting child documents >> 0:00:10.611130
====================================== Total: 0:00:10.612292

但是,当我嵌套 TimerGroups 时,它搞砸了:

with TimerGroup("Choosing the best classifier for %s context" % context_name):
with Timer("Splitting datasets"):
# some code...
for cname, cparams in classifiers.items():
with TimerGroup("%s classifier" % cname):
with Timer("Training"):
# some code...
with Timer("Calculating accuracy on testing set"):
# some code


= Choosing the best classifier for Global context ==========
Splitting datasets >> 0:00:00.002054
= Naive Bayes classifier ===================================
Training >> 0:00:34.184903
Calculating accuracy on testing set >> 0:05:08.481904
====================================== Total: 0:05:42.666949

====================================== Total: 0:05:42.669078

我所需要做的就是以某种方式缩进嵌套的 Timers 和 TimerGroups。我应该将任何参数传递给它们的构造函数吗?或者我可以从类(class)内部检测到吗?

最佳答案

没有检测嵌套上下文管理器的特殊工具,没有。你必须自己处理这件事。您可以在自己的上下文管理器中执行此操作:

import threading


class TimerGroup(Timer):
_active_group = threading.local()

def __enter__(self):
if getattr(TimerGroup._active_group, 'current', False):
raise RuntimeError("Can't nest TimerGroup context managers")
TimerGroup._active_group.current = self
print(('= ' + self.name + ' ').ljust(line_width, '='))
return self

def __exit__(self, exc_type, exc_val, exc_tb):
TimerGroup._active_group.current = None
total_time = self.seconds_to_str(self.end())
print(" Total: {0}".format(total_time).rjust(line_width, '='))
print()

然后您可以在别处使用 TimerGroup._active_group 属性来获取当前事件的组。我用了 thread-local object以确保它可以跨多个执行线程使用。

或者,您可以将其设为堆栈计数器并在嵌套的 __enter__ 调用中递增和递减,或者将其设为堆栈 list 并推送 self到那个堆栈上,当你 __exit__ 时再次弹出它:

import threading


class TimerGroup(Timer):
_active_group = threading.local()

def __enter__(self):
if not hasattr(TimerGroup._active_group, 'current'):
TimerGroup._active_group.current = []
stack = TimerGroup._active_group.current
if stack:
# nested context manager.
# do something with stack[-1] or stack[0]
TimerGroup._active_group.current.append(self)

print(('= ' + self.name + ' ').ljust(line_width, '='))
return self

def __exit__(self, exc_type, exc_val, exc_tb):
last = TimerGroup._active_group.current.pop()
assert last == self, "Context managers being exited out of order"
total_time = self.seconds_to_str(self.end())
print(" Total: {0}".format(total_time).rjust(line_width, '='))
print()

关于python - 检测上下文管理器嵌套,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44804688/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com