假设我有一个上下文管理器:
@contextmanager
def cm(x):
y = f(x)
z = yield y
g(z)
Run Code Online (Sandbox Code Playgroud)
如何发送z到上下文管理器?
我试过:
my_cm = cm()
with my_cm:
my_cm.gen.send(123)
Run Code Online (Sandbox Code Playgroud)
但我得到 StopIteration,这可能是因为send产量?
我经常遇到这样的情况:根据某些命令行参数,输入可能来自文件或标准输入。输出也是如此。我真的很喜欢 python 3 中上下文管理器的工作方式,因此尝试让我的所有open调用成为某个with语句的一部分。但在这种情况下,我遇到了麻烦。
if args.infile:
with open(args.infile, "r") as f:
process(f)
else:
process(sys.stdin)
Run Code Online (Sandbox Code Playgroud)
已经很笨拙了,并且对于输入和输出我必须满足四种组合。我想要更简单的东西,例如
with (open(args.infile, "r") if args.infile
else DummyManager(sys.stdin)) as f:
process(f)
Run Code Online (Sandbox Code Playgroud)
python 标准库中有类似 DummyManager 的东西吗?实现上下文管理器协议的东西,但仅从其方法返回固定值__enter__?我想这样一个类最有可能的位置是contextlib,并且由于我在那里没有找到类似的东西,也许没有这样的东西。您还可以建议其他优雅的解决方案吗?
我想使用一个对象作为上下文管理器,但控制__exit__调用该方法的时刻。
特别是,我正在使用Session()Python requests 模块提供的对象,它可以用作上下文管理器。我理解,通过简单地使用例如每次创建和销毁requests.get()一个新对象,而不是持久化会话应该给出更短的响应时间并为会话中的所有请求保留标头等。Session()我想x使用 a 发出请求Session(),然后关闭会话并y使用新Session()对象发出请求,依此类推,直到我的代码完成运行。但是,由于我的代码中有各种调用Session().get(),因此我不想将其全部包含在一个with块中。我有什么选择?
对于更有经验的 Python 程序员来说,这可能是一个简单的问题,但我发现自己陷入了如何组织代码的困境中。关于如何实现这一点有什么想法吗?如果需要,很乐意提供任何说明。谢谢。
考虑这个threading.Thread类:
class Sleeper(threading.Thread):
def __init__(self, sleep=5.0):
threading.Thread.__init__(self)
self.event = threading.Event()
self.sleep = sleep
def run(self):
while self.sleep > 0 and not self.event.is_set():
self.event.wait(1.0)
self.sleep -= 1
def stop(self):
self.event.set()
Run Code Online (Sandbox Code Playgroud)
它会休眠一定的时间,并在达到该时间之前退出或停止。
我用它作为:
sleeper = Sleeper()
try:
sleeper.start()
# do stuffs here
except:
# handle possible exceptions here
finally:
sleeper.stop()
Run Code Online (Sandbox Code Playgroud)
我更愿意像上下文管理器一样使用它:
with Sleeper():
# do stuffs here
Run Code Online (Sandbox Code Playgroud)
然后线程在退出with块时停止。
我尝试过添加__enter__和__exit__方法,它似乎有效,但我不确定这是正确的方法:
def __enter__(self):
self.start()
return self
Run Code Online (Sandbox Code Playgroud)
和
def __exit__(self, type, value, traceback):
self.stop()
Run Code Online (Sandbox Code Playgroud)
但我真的不确定我在这里做什么。应该如何正确进行呢?
我想以这样的方式定义一个属性,无论何时调用它,它都是在上下文管理器中完成的。说吧,我从以下开始:
@property
def hangar(self):
return self._hangar
Run Code Online (Sandbox Code Playgroud)
每当写下代码时,我都会写:
res = some_function(self.hangar)
Run Code Online (Sandbox Code Playgroud)
我希望它被评价为:
with pandas.HDFStore(...) as hangar:
some_function(self.hangar)
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
我最近一直在研究Python的contextmanager(更具体地说,Python 3的contextlib或其向后移植的contextlib2),我想知道将它们编写为类与函数相比有何优点/缺点?
它们似乎都以相同的方式运行并以相同的方式处理异常。有很多很酷的实用程序,例如 ExitStack(),但这些实用程序似乎可以在编写为类或函数的上下文管理器中实现。因此,我正在努力寻找一个很好的理由来解释为什么人们想要将上下文管理器详细地编写为一个类,而它们可以被编写为一个函数并且只需使用 contextmanager 装饰器即可。
这是我写的一个简单的例子,展示了两者做同样的事情:
# !/usr/bin/python -u
# encoding: utf-8
from contextlib import contextmanager
# Function-based
@contextmanager
def func_custom_open(filename, mode):
try:
f = open(filename, mode)
yield f
except Exception as e:
print(e)
finally:
f.close()
# Class-based
class class_custom_open(object):
def __init__(self, filename, mode):
self.f = open(filename, mode)
def __enter__(self):
return self.f
def __exit__(self, type, value, traceback):
self.f.close()
if __name__ == '__main__':
# Function-based
with func_custom_open('holafile_func.txt', 'w') as func_f:
func_f.write('hola func!')
# Class-based
with class_custom_open('holafile_class.txt', 'w') as class_f:
class_f.write('hola …Run Code Online (Sandbox Code Playgroud) 我已经使用了f = h5py.File(filename, 'r')一段时间了,f.close()最后需要用 来关闭。
最近我发现我可以这样做:
with h5py.File(filename, 'r') as f:
# code to manipulate the file
Run Code Online (Sandbox Code Playgroud)
但是我不确定:这个“上下文管理器”(他们在页面上称之为)是否会自动关闭文件,还是我仍然需要f.close()在最后添加?
我试图在文档中找到答案,但上下文管理器仅在快速入门指南中的一行中提到,显然没有关于它的更多信息。
是否可以根据某些条件使用不同的上下文管理器执行单个块?
例子:
if some_condition:
with ContextManager(**args) as contex:
... # some block
else:
with OtherContextManager(**other_args) as contex:
... # the same block
Run Code Online (Sandbox Code Playgroud)
一种方法是包装...到一个函数中,但这对我来说可能不太方便。还有另一种可能吗?
长话短说,让第二段代码与第一段代码完全一样工作的正确方法是什么?
stack_device = [None]
stack_context = [None]
@contextlib.contextmanager
def device(device):
stack_device.append(device)
try:
yield
finally:
stack_device.pop()
@contextlib.contextmanager
def context(ctx):
stack_context.append(ctx)
try:
with device("dev"):
yield
finally:
stack_context.pop()
with context("myctx"):
print(stack_device[-1]) # -> dev
print(stack_context[-1]) # -> ctx
Run Code Online (Sandbox Code Playgroud)
当然,当我需要它时,那个设备不会设置正确的设备:
stack_device = [None]
stack_context = [None]
class Device():
def __init__(self, device):
self.device = device
def __enter__(self):
stack_device.append(self.device)
return
def __exit__(self, type, value, traceback):
stack_device.pop()
class Context():
def __init__(self, ctx):
self.ctx = ctx
def __enter__(self):
with Device("cls_dvc"):
stack_context.append(self.ctx)
return
def __exit__(self, type, value, traceback):
stack_context.pop() …Run Code Online (Sandbox Code Playgroud) 我有一个从上下文管理器产生的函数:
def producer(pathname):
with open(pathname) as f:
while True:
chunk = f.read(4)
if not chunk:
break
yield chunk
Run Code Online (Sandbox Code Playgroud)
当生成器完全被消耗时这不是问题,因为在最后一次迭代期间,生成器在yield语句之后恢复执行,并且循环中断并且我们很好地退出上下文管理器。
但是,如果生成器仅被部分消耗,并且没有更多的消费者将其完全消耗,那么生成器是否会永远处于暂停状态?在这种情况下,我们永远不会退出上下文管理器。这是否意味着该文件将在程序执行的其余部分保持打开状态?或者至少直到生成器被垃圾收集为止?这是我应该自己处理的极端情况,还是我可以依靠 Python 运行时来及时关闭悬空的上下文管理器?
contextmanager ×10
python ×9
python-3.x ×4
generator ×2
class ×1
decorator ×1
function ×1
h5py ×1
pandas ×1
properties ×1
session ×1
stdin ×1