标签: contextmanager

如何将装饰器与 @contextmanager 装饰器混合使用?

这是我正在使用的代码:

from contextlib import contextmanager
from functools import wraps
class with_report_status(object):

    def __init__(self, message):
        self.message = message

    def __call__(self, f):
        @wraps(f)
        def wrapper(_self, *a, **kw):
            try:
                return f(_self, *a, **kw)
            except:
                log.exception("Handling exception in reporting operation")
                if not (hasattr(_self, 'report_status') and _self.report_status):
                    _self.report_status = self.message
                raise

        return wrapper

class MyClass(object):

    @contextmanager
    @with_report_status('unable to create export workspace')
    def make_workspace(self):
        temp_dir = tempfile.mkdtemp()
        log.debug("Creating working directory in %s", temp_dir)
        self.workspace = temp_dir
        yield self.workspace
        log.debug("Cleaning up working directory in %s", temp_dir)
        shutil.rmtree(temp_dir) …
Run Code Online (Sandbox Code Playgroud)

python decorator contextmanager

5
推荐指数
1
解决办法
3063
查看次数

将 Python 上下文管理器的迭代器嵌套在“with”中

我有一个返回上下文管理器的迭代器。

我想要一个 pythonicwith语句,它模拟多个嵌套语句的行为with,每个嵌套语句对应迭代器返回的每个上下文管理器。

有人可能会说,我想要(已弃用的)函数的泛化contextlib.nested

python iterator nested contextmanager

5
推荐指数
1
解决办法
3407
查看次数

如何嵌套任意数量的Python文件上下文管理器?

我想采用任意数量的路径来表示嵌套的tar档案,并对最里面的档案执行操作.问题是,嵌套可以是任意的,因此我需要的上下文管理器的数量也是任意的.

举个例子:

ARCHIVE_PATH = "path/to/archive.tar"

INNER_PATHS = (
    "nested/within/archive/one.tar",
    "nested/within/archive/two.tar",
    # Arbitary number of these
)

def list_inner_contents(archive_path, inner_paths):
    with TarFile(archive_path) as tf1:
        with TarFile(fileobj=tf1.extractfile(inner_paths[0])) as tf2:
            with TarFile(fileobj=tf2.extractfile(inner_paths[1])) as tf3:
                # ...arbitary level of these!
                return tfX.getnames()

contents = list_inner_contents(ARCHIVE_PATH, INNER_PATHS))
Run Code Online (Sandbox Code Playgroud)

我不能使用with语句的嵌套语法,因为可以嵌套任意数量的级别.我无法使用,contextlib.nested因为文档在那里说:

... nested()用于打开两个文件是一个编程错误,因为如果在打开第二个文件时抛出异常,第一个文件将不会立即关闭.

有没有办法使用语言结构来执行此操作,还是需要手动管理我自己的打开文件对象堆栈?

python contextmanager python-2.7

5
推荐指数
1
解决办法
269
查看次数

上下文管理器类的命名约定("with"blocks)

对于要在with块中使用的类或函数是否存在通用命名约定,例如

with CreateSomeContext() as x:
    ...
Run Code Online (Sandbox Code Playgroud)

?是否表示应该使用函数的类或结果with

python naming-conventions contextmanager

5
推荐指数
2
解决办法
696
查看次数

对Python的正确顺序感到困惑

我读到这里,它是推荐使用with open(filename),而不是使用对open(filename)filename.close()(至少对基本任务),并且它也是更好地使用try.

Q1:如果我的理解是正确的,那么正确的顺序是什么?

try:
  with open(filename) as f:
    do something, eg. match string
Run Code Online (Sandbox Code Playgroud)

要么

with open(filename) as f:
  try:
    do something, eg. match string
Run Code Online (Sandbox Code Playgroud)

Q2:如果我还想插入一些代码来弹出文件处理错误的弹出窗口,哪种情况更好?(找不到文件,或者其他东西)

python try-catch with-statement contextmanager

5
推荐指数
1
解决办法
72
查看次数

在生成器中使用 with 语句是否明智?

考虑以下 Python 代码:

def values():
    with somecontext():
        yield 1
        yield 2
for v in values():
    print(v)
    break
Run Code Online (Sandbox Code Playgroud)

在这种情况下,Python 是否保证生成器已正确关闭,从而退出上下文?

我意识到在实践中,由于引用计数和生成器的急切破坏,在 CPython 中会出现这种情况,但是 Python 是否保证这种行为?我确实注意到它在 Jython 中确实不起作用,所以这应该被视为错误还是允许的行为?

python generator with-statement contextmanager

5
推荐指数
1
解决办法
663
查看次数

为什么模块不能成为上下文管理器(对'with'语句)?

假设我们有以下内容mod.py:

def __enter__():
    print("__enter__<")

def __exit__(*exc):
    print("__exit__< {0}".format(exc))

class cls:
    def __enter__(self):
        print("cls.__enter__<")

    def __exit__(self, *exc):
        print("cls.__exit__< {0}".format(exc))
Run Code Online (Sandbox Code Playgroud)

以及它的以下用途:

import mod

with mod:
    pass
Run Code Online (Sandbox Code Playgroud)

我收到一个错误:

Traceback (most recent call last):
  File "./test.py", line 3, in <module>
    with mod:
AttributeError: __exit__
Run Code Online (Sandbox Code Playgroud)

根据文档文档,该with语句应如下执行(我相信它在步骤2失败,因此截断列表):

  1. 评估上下文表达式(with_item中给出的表达式)以获取上下文管理器.
  2. __exit__()加载上下文管理器以供以后使用.
  3. __enter__()调用上下文管理器的方法.
  4. 等等...

据我所知,没有理由找不到原因__exit__.是否有一些我错过了使模块无法作为上下文管理器工作的东西?

python python-module with-statement contextmanager python-3.x

5
推荐指数
1
解决办法
702
查看次数

尽管已正确设置,但Python记录器不会打印调试消息

我有以下代码,我只想 使用contextmanager来使用日志记录模块.

from contextlib import contextmanager
import logging

@contextmanager
def log_level(level, name):
    logger = logging.getLogger(name)
    old_level = logger.getEffectiveLevel()
    print('log_level.old_level: ' + str(old_level))
    logger.setLevel(level)
    print('log_level.new_level: ' + str(logger.getEffectiveLevel()))
    try:
        yield logger
    finally:
        logger.setLevel(old_level)

if __name__ == '__main__':

    with log_level(logging.DEBUG, 'my-log') as logger:
        print('__main__.log_level.logger.level: ' + str(logger.getEffectiveLevel()))
        logger.debug('Debug with logger: will print')
        logger.warning('Warning')
        print('__main__.log_level.logger.level: ' + str(logger.getEffectiveLevel()))
    print('__main__.logger.level: ' + str(logger.getEffectiveLevel()))
Run Code Online (Sandbox Code Playgroud)

可以看出,在main.log_level中,记录器级别应该是DEBUG,它应该打印消息'Debug with logger:will print'.但是,当我运行代码时,此调试消息不会打印.查看代码的打印件,它表示记录器在log_level内部具有DEBUG级别,并且当它退出log_level时级别返回到WARNING.这是我的输出,当使用python 3执行时:

log_level.old_level: 30
log_level.new_level: 10
__main__.log_level.logger.level: 10
Warning
__main__.log_level.logger.level: 10
__main__.logger.level: 30
Run Code Online (Sandbox Code Playgroud)

我想帮助理解为什么 …

python logging contextmanager python-3.x

5
推荐指数
1
解决办法
5486
查看次数

在3.5中键入__exit__在运行时失败,但是类型检查

什么是正确的类型签名__exit__?我有以下几点:

from types import TracebackType
from typing import Optional, Type

class Foo:
    def __enter__(self) -> 'Foo':
        return self

    def __exit__(self, exc_type: Optional[Type[BaseException]],
                 exc_value: Optional[BaseException],
                 traceback: Optional[TracebackType]) -> bool:
        return False
Run Code Online (Sandbox Code Playgroud)

在最近的mypy(0.560)上,此类型检查是否正确(--strict我对此签名有一定的信心,因为我从排版的内部偷了它)。

当此脚本与python 3.6一起运行时,按预期没有任何反应。但是当使用3.5.2运行时,我们会得到一个例外:

Traceback (most recent call last):
  File "/home/student/mypy_test/test.py", line 4, in <module>
    class Foo: #(ContextManager['Foo']):
  File "/home/student/mypy_test/test.py", line 8, in Foo
    def __exit__(self, exc_type: Optional[Type[BaseException]],
  File "/usr/lib/python3.5/typing.py", line 649, in __getitem__
    return Union[arg, type(None)]
  File "/usr/lib/python3.5/typing.py", line 552, in __getitem__
    dict(self.__dict__), parameters, _root=True)
  File …
Run Code Online (Sandbox Code Playgroud)

python contextmanager python-3.x python-3.5 mypy

5
推荐指数
1
解决办法
753
查看次数

手动打开上下文管理器

我的问题是,如何在不使用的情况下执行任何上下文管理器with


Python 有上下文管理器的思想,

代替

file = open('some_file', 'w')
try:
    file.write('Hola!')
finally:
    file.close()
# end try
Run Code Online (Sandbox Code Playgroud)

你可以写

with open('some_file', 'w') as opened_file:
    opened_file.write('Hola!')
# end with
Run Code Online (Sandbox Code Playgroud)

虽然在大多数情况下,第二个是黄金解决方案,但对于在交互式控制台中进行测试和探索,第一个可以更好地使用,因为您可以一行一行地编写它。

>>> file = open('some_file', 'w')
>>> file.write('Hola!')
>>> file.close()
Run Code Online (Sandbox Code Playgroud)

我的问题是,我如何执行这样的with上下文管理器,最适合探索?


我的实际用例如下,但请尝试给出一个通用的答案,并且也适用于其他上下文管理器。

import flask

app = flask.Flask(__name__)

with app.test_request_context('/?name=Peter'):
    assert flask.request.path == '/'
    assert flask.request.args['name'] == 'Peter'
Run Code Online (Sandbox Code Playgroud)

来自烧瓶文档

python with-statement contextmanager

5
推荐指数
1
解决办法
1629
查看次数