标签: contextmanager

functools.wraps不允许我用Python 3中的类包装函数

我想为一些将文件作为第一个参数的函数编写装饰器.装饰器必须实现上下文管理器协议(即将包装函数转换为上下文管理器),所以我想我需要用类包装函数.

我对装饰模式并不熟悉,之前从未实现过上下文管理器,但是我写的内容在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)

python decorator contextmanager python-3.x functools

6
推荐指数
1
解决办法
2256
查看次数

Python中的Multiline with子句

如何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风格指南,它禁止反斜杠线延续.

python styles contextmanager

6
推荐指数
1
解决办法
1086
查看次数

什么是在生成器内部时触发上下文管理器的__exit__?

我正在制作像使用生成器作为协程的任务调度程序.在下面的代码中,我需要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)

python garbage-collection generator contextmanager

6
推荐指数
1
解决办法
677
查看次数

如何使用 SQLAlchemy 上下文管理器并仍然获取行 ID?

我正在使用提供的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)

我错过了什么?

python transactions sqlalchemy contextmanager

6
推荐指数
1
解决办法
2028
查看次数

python3上下文管理器强制提前退出

我需要创建一个上下文管理器,当满足某些条件时,可以强制它提前退出.

更多细节:

上下文管理器需要处理检查/锁定/释放资源.在__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__调用它并且不执行上下文代码.有没有办法调整上述任何一个想法来做到这一点?或者还有另一种方式吗?

contextmanager python-3.x

6
推荐指数
1
解决办法
917
查看次数

在 lambda 中使用上下文管理器,如何?

如何在 lambda 中使用上下文管理器?接受黑客攻击。暂缓认为这是 lambda 的错误用法的观点。

我知道我可以这样做:

def f():
    with context():
        return "Foo"
Run Code Online (Sandbox Code Playgroud)

但我想做这样的事情:

lambda: with context(): "Foo"
Run Code Online (Sandbox Code Playgroud)

python lambda with-statement contextmanager

6
推荐指数
1
解决办法
1890
查看次数

在 __enter__ 中输入上下文管理器

将上下文管理器定义为函数,可以很容易地以编程方式从其中输入一个单独的(或递归的)上下文管理器,如下所示:

@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 macros contextmanager

6
推荐指数
1
解决办法
3769
查看次数

在python中调用上下文管理器的多种方法


背景

我在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)

python class python-2.x contextmanager python-2.7

6
推荐指数
1
解决办法
309
查看次数

上下文管理器的类型提示

我想要一个 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)

不起作用。

type-hinting contextmanager python-3.x

6
推荐指数
1
解决办法
5252
查看次数

为什么我的上下文管理器不会因异常而退出

我正在学习上下文管理器,并试图自己构建一个。以下是一个虚拟上下文管理器,它以读取模式打开一个文件(我知道我可以这样做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)

python contextmanager python-decorators

6
推荐指数
1
解决办法
715
查看次数