我想为一些将文件作为第一个参数的函数编写装饰器.装饰器必须实现上下文管理器协议(即将包装函数转换为上下文管理器),所以我想我需要用类包装函数.
我对装饰模式并不熟悉,之前从未实现过上下文管理器,但是我写的内容在Python 2.7中有效,如果我注释掉它,它也适用于Python 3.3 wraps.
from functools import wraps
def _file_reader(func):
"""A decorator implementing the context manager protocol for functions
that read files."""
# @wraps(func)
class CManager:
def __init__(self, source, *args, **kwargs):
self.source = source
self.args = args
self.kwargs = kwargs
self.close = kwargs.get('close', True)
def __enter__(self):
# _file_obj is a little helper that opens the file for reading
self.fsource = _file_obj(self.source, 'r')
return func(self.fsource, *self.args, **self.kwargs)
def __exit__(self, exc_type, exc_value, traceback):
if self.close:
self.fsource.close()
return False …Run Code Online (Sandbox Code Playgroud) 如何with在Python中通过多行传播long 子句?现在,我有
with self.context_manager_one(some, parameters, that, are, passed) \
as return_value_one, \
self.context_manager_two(self.p, slice(None), None) \
as return_value_two:
Run Code Online (Sandbox Code Playgroud)
我想按照谷歌的Python风格指南,它禁止反斜杠线延续.
我正在制作像使用生成器作为协程的任务调度程序.在下面的代码中,我需要print cleanup确定性地执行.
从我的交互看来,将对象释放到垃圾收集器会导致上下文管理器退出.但是,我知道最好不要依赖GC的时间.它真的是GC调用__exit__它还是另一种机制?
我怎么能严格强迫print 'cleanup'?
>>> from contextlib import contextmanager
>>> @contextmanager
... def foo():
... print 'setup'
... try:
... yield
... finally:
... print 'cleanup'
...
>>> def bar():
... with foo():
... while True:
... yield 'bar'
...
>>> b = bar()
>>> b.next()
setup
'bar'
>>> b = None
cleanup
Run Code Online (Sandbox Code Playgroud) 我正在使用提供的contextmanagerSQLAlchemy来为我处理会话。我不明白的是如何获取自动生成的 ID,因为 (1) 在commit()调用之后才创建 ID (2) 新创建的实例仅在上下文管理器的范围内可用:
def save_soft_file(name, is_geo=False):
with session_scope() as session:
soft_file = models.SoftFile(name=name, is_geo=is_geo)
session.add(soft_file)
# id is not available here, because the session has not been committed
# soft_file is not available here, because the session is out of context
return soft_file.id
Run Code Online (Sandbox Code Playgroud)
我错过了什么?
我需要创建一个上下文管理器,当满足某些条件时,可以强制它提前退出.
更多细节:
上下文管理器需要处理检查/锁定/释放资源.在__enter__,上下文管理器需要检查资源是否被锁定.如果是,我想在__exit__不执行上下文中的代码的情况下调用.否则,上下文管理器获取资源,执行上下文代码,并清理资源__exit__.
它可能看起来像这样:
class my_context_manager:
def __enter__(self):
if resource_locked():
self.__exit__(None, ResourceLockedException(), None)
else:
acquire_resource()
def __exit__(self, *exc_info):
if not isinstance(exc_info[1], ResourceLockedException):
release_resource()
else:
log.warn("Resource already in use.")
Run Code Online (Sandbox Code Playgroud)
但是,上面的代码实际上并不起作用,因为调用__exit__内部__enter__并不会阻止上下文中的代码被执行.
或者,我可以ResourceLockedException从内部抛出__enter__,但之后__exit__不会被调用,因为异常将从上下文管理器本身抛出.我希望能够捕获异常,记录警告,如果资源被锁定则不输入上下文.
这归结为找到一些早期关闭上下文的方法,因此__exit__调用它并且不执行上下文代码.有没有办法调整上述任何一个想法来做到这一点?或者还有另一种方式吗?
如何在 lambda 中使用上下文管理器?接受黑客攻击。暂缓认为这是 lambda 的错误用法的观点。
我知道我可以这样做:
def f():
with context():
return "Foo"
Run Code Online (Sandbox Code Playgroud)
但我想做这样的事情:
lambda: with context(): "Foo"
Run Code Online (Sandbox Code Playgroud) 将上下文管理器定义为函数,可以很容易地以编程方式从其中输入一个单独的(或递归的)上下文管理器,如下所示:
@contextmanager
def enter(times):
if times:
with enter(times - 1) as tup:
print 'entering {}'.format(times)
yield tup + (times,)
print 'exiting {}'.format(times)
else:
yield ()
Run Code Online (Sandbox Code Playgroud)
运行这个:
In [11]: with enter(4) as x:
....: print x
....:
entering 1
entering 2
entering 3
(1, 2, 3)
exiting 3
exiting 2
exiting 1
Run Code Online (Sandbox Code Playgroud)
所有出入境记账都为您完成,多好啊!但是如果你有一个类,而不是一个函数怎么办?
class Enter(object):
def __init__(self, times):
self.times = times
def __enter__(self):
print 'entering {}'.format(self.times)
if self.times:
with Enter(self.times - 1) as tup: # WRONG
return tup + (self.times,)
return …Run Code Online (Sandbox Code Playgroud) 我在python中有一个类,它接受一个互斥体列表.然后它对该列表进行排序,并使用__enter__()和__exit__()以特定顺序锁定/解锁所有互斥锁以防止死锁.
该类目前为我们节省了很多潜在的死锁麻烦,因为我们可以用RAII风格调用它,即:
self.lock = SuperLock(list_of_locks)
# Lock all mutexes.
with self.lock:
# Issue calls to all hardware protected by these locks.
Run Code Online (Sandbox Code Playgroud)
我们想公开这个类的方法来提供RAII风格的API,这样我们可以在以某种方式调用时一次只锁定一半的互斥锁,即:
self.lock = SuperLock(list_of_locks)
# Lock all mutexes.
with self.lock:
# Issue calls to all hardware protected by these locks.
# Lock the first half of the mutexes in SuperLock.list_of_locks
with self.lock.first_half_only:
# Issue calls to all hardware protected by these locks.
# Lock the second half of the mutexes in …Run Code Online (Sandbox Code Playgroud) 我想要一个 pyplot 图形的上下文管理器,基本上像这样:
from contextlib import contextmanager
import matplotlib.pyplot as plt
@contextmanager
def subplots():
(fig, ax) = plt.subplots()
try:
yield (fig, ax)
finally:
plt.close(fig)
Run Code Online (Sandbox Code Playgroud)
是否可以对返回的元组实现类型提示?天真的
import typing
def subplots() -> typing.Tuple[plt.Figure, plt.Axes]
Run Code Online (Sandbox Code Playgroud)
不起作用。
我正在学习上下文管理器,并试图自己构建一个。以下是一个虚拟上下文管理器,它以读取模式打开一个文件(我知道我可以这样做with open(...): ...。这只是我构建的一个示例,旨在帮助我了解如何创建自己的上下文管理器):
@contextmanager
def open_read(path: str):
f = open(path, 'r')
print('open')
yield f
f.close()
print('closed')
def foo():
try:
with open_read('main.py') as f:
print(f.readline())
raise Exception('oopsie')
except Exception:
pass
print(f.readline())
foo()
Run Code Online (Sandbox Code Playgroud)
我希望这段代码能够打印:
open
<line 1 of a.txt>
closed
ValueError: I/O operation on closed file.
Run Code Online (Sandbox Code Playgroud)
但它打印的是:
open
<line 1 of a.txt>
<line 2 of a.txt>
Run Code Online (Sandbox Code Playgroud)
它没有关闭文件!
这似乎与 python 的文档相矛盾,该文档声明无论语句成功退出还是出现异常__exit__都会调用该函数:with
目的。退出(自身、exc_type、exc_value、回溯)
退出与该对象相关的运行时上下文。参数描述导致上下文退出的异常。如果上下文退出时没有异常,则所有三个参数都将为 None。
有趣的是,当我重新实现上下文管理器(如下所示)时,它按预期工作:
open
<line 1 of a.txt>
closed
ValueError: I/O operation on closed …Run Code Online (Sandbox Code Playgroud) contextmanager ×10
python ×8
python-3.x ×3
class ×1
decorator ×1
functools ×1
generator ×1
lambda ×1
macros ×1
python-2.7 ×1
python-2.x ×1
sqlalchemy ×1
styles ×1
transactions ×1
type-hinting ×1