标签: contextmanager

是否有可能创建一个上下文敏感的python上下文管理器来保存,修改和恢复状态?

我有一对python函数,目前在两个值之间翻转一个全局变量.我想把它们变成上下文管理器,所以我可以将它们用作with块,在块内设置变量,但之后恢复它.这是所需的行为:

>>> MODE
'user'
>>> mode_sudo()  # Sets MODE to 'sudo'...
>>> MODE
'sudo'
>>> mode_user()  # Sets MODE to 'user'...
>>> MODE
'user'
>>> with mode_sudo():
...    print MODE
'sudo'
>>> MODE
'user'
Run Code Online (Sandbox Code Playgroud)

这样的嵌合体可能吗?

更新:为了清楚起见,这里是仅限上下文管理器的实现:

from contextlib import contextmanager

@contextmanager
def mode_sudo():
    global MODE
    old_mode = MODE
    MODE = 'sudo'
    yield
    MODE = old_mode

@contextmanager
def mode_user():
    global MODE
    old_mode = MODE
    MODE = 'user'
    yield
    MODE = old_mode
Run Code Online (Sandbox Code Playgroud)

用关键字调用这些w/oa会返回一个生成器.有没有办法通过普通香草函数调用和巧克力上下文管理器获得模式翻转行为?

python state stateful contextmanager

3
推荐指数
1
解决办法
1622
查看次数

为zipfile定义的__enter__和__exit__在哪里?

基于with声明

  • __exit__()加载上下文管理器以供以后使用.
  • __enter__()调用上下文管理器的方法.

我已经看到了一个与zipfile有关的用法

问题>我已经检查了位于此处的zipfile的源代码:

/usr/lib/python2.6/zipfile.py

我不知道__enter____exit__函数的定义在哪里?

谢谢

python with-statement contextmanager

3
推荐指数
1
解决办法
1017
查看次数

Python:在类方法上使用contextmanager的意外行为

我正在尝试使用Python中的with..as contruct来简化"可逆计算"代码的编写.但是,@contextmanager在类方法上使用似乎会更改未来类实例的默认初始化.Python 2.6和3.1具有相同的行为.这是一个展示此行为的简单示例:

#!/usr/bin/env python

import contextlib

class SymList:
    def __init__(self, L=[]):
        self.L = L

    @contextlib.contextmanager
    def SymAdd(self, a):
        self.L.append(a)
        yield
        self.L.append(a)

SL = SymList()
with SL.SymAdd(3):
    SL.L.append(5)
print(SL.L) # Expect and see [3, 5, 3]
SL2 = SymList()
print(SL2.L) # Expect [] and see [3, 5, 3]
Run Code Online (Sandbox Code Playgroud)


  • 为什么不是SL2一个新的实例SymList
  • SL2.L数据成员如何引用SL.L数据成员?

python with-statement contextmanager

3
推荐指数
1
解决办法
3135
查看次数

上下文管理器出口在体内代码之前调用

我一直在玩Python自己的上下文管理器.我看到一些奇怪的行为很可能是由于我的实施.

我看到__exit__在'with'上下文中的语句之前调用的代码.例如,以下是代码段:

with ProgressBar(10) as p:
  p.update(1)
Run Code Online (Sandbox Code Playgroud)

这是例外:

Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
AttributeError: 'NoneType' object has no attribute 'update'
Run Code Online (Sandbox Code Playgroud)

我把调试中的所有__enter__,__exit__和更新我的上下文管理器的方法.它看起来像是__exit__在update()之前调用的.这没有任何意义所以我必须遗漏一些简单的东西.

这是我的简单上下文管理器类:

class ProgressBar(object):
    """Progress bar that normalizes progress to [0 - 100] scale"""

    def __init__(self, max_value):
        """Create progress bar with max_value"""

        self._current_value = 0.0
        self._completed_value = 100.0
        self._max_value = float(max_value)
        print 'init', max_value

    def __enter__(self):
        """Start of context manager, 'with' statement"""

        print 'enter'
        self._current_value = …
Run Code Online (Sandbox Code Playgroud)

python contextmanager

3
推荐指数
1
解决办法
1977
查看次数

在Context Manager - Python期间发生捕获异常

可能重复:
使用带有try-except块的python"with"语句

我正在用openPython打开一个文件.我将文件处理封装在一个with语句中:

with open(path, 'r') as f:
    # do something with f
    # this part might throw an exception
Run Code Online (Sandbox Code Playgroud)

这样我就确定我的文件已关闭,即使抛出了异常.

但是,我想处理打开文件失败的情况(OSError抛出一个).一种方法是将整个with块放在一个try:.只要文件处理代码不引发OSError,这就可以工作.

它可能看起来像:

try:
   with open(path, 'rb') as f:
except:
   #error handling
       # Do something with the file
Run Code Online (Sandbox Code Playgroud)

这当然不起作用,真的很难看.这样做有一种聪明的方法吗?

谢谢

PS:我正在使用python 3.3

python contextmanager python-3.x

3
推荐指数
1
解决办法
1102
查看次数

是否可以在上下文管理器的__exit __()方法中访问上下文对象(代码块)?

我想在exit()方法中再次调用代码对象,如果它引发异常(可能是几次,可能有延迟).我知道装饰器很容易,但我的动机是有时候我想重复一些代码片段,我不想提取到一个单独的函数并装饰它.我正在寻找这些方面的东西:

class again(object):
    def __enter__(self):
        pass

    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type is not None:
            ????        # Invoke the code object again
            return True # eat exception
Run Code Online (Sandbox Code Playgroud)

它会像这样使用:

x = 0
with again():
    print x
    x += 1
    if x == 1:
         raise Exception('I hate 1')
Run Code Online (Sandbox Code Playgroud)

而预期的产出将是:

0
1  
Run Code Online (Sandbox Code Playgroud)

我可以找到一种方法来获取代码对象.没有任何上下文管理器属性似乎引用它(我想这不是真正需要的,因为它的工作只是在前后做事).

有可能吗?

python contextmanager

3
推荐指数
1
解决办法
699
查看次数

使用urllib.request.urlopen发出请求时使用contextlib.closing是否有优势?

为了说明我的问题,这是一个不使用的基本请求contextlib:

    import urllib.request

    url = "http://www.example.com/"

    with urllib.request.urlopen(url) as response:
        raw_data = response.read()
Run Code Online (Sandbox Code Playgroud)

并使用相同的请求contextlib:

    import contextlib
    import urllib.request


    url = "http://www.example.com/"

    with contextlib.closing(urllib.request.urlopen(url)) as response:
        raw_data = response.read()
Run Code Online (Sandbox Code Playgroud)

据我所知,这两个请求具有相同的结果:检索数据,请求在代码块完成时自动关闭,raw_data即使在请求关闭后也可以访问.在使用请求时urllib.request.urlopen,是否有使用优势contextlib.closing或是多余的?一种方法更像Pythonic和/或更常见吗?

python urllib contextmanager python-3.x

3
推荐指数
1
解决办法
418
查看次数

如何在装饰器中使用上下文管理器以及如何将在decorator中创建的对象传递给装饰函数

我有一个测试类,需要在最后进行一些清理.为了确保用户不会忘记这样做,我想在类中添加一个上下文管理器.我还有一个装饰器,我想在其中使用此上下文管理器来创建测试类的对象并将其传递给装饰函数.它甚至可能吗?

这就是我要做的事情:

class test:
    def __init__(self, name):
        self._name = name
        print "my name is {0}".format(name)

    def exit():
        print "exiting"

    @contextmanager
    def testcm(self):
        print "inside cm"
        try:
            yield self
        finally:
            self.exit()

    def randomtest(self, str):
        print "Inside random test {0}".format(str)


def decorate(name):
    def wrapper(testf):
        def testf_wrapper(test):
            with test(name).testcm() as testobj:
                return testf(testobj)
            return testf_wrapper
        return wrapper
    return decorate

@decorate("whatever")
def testf(testobj):
    testobj.randomtest("randomness")
Run Code Online (Sandbox Code Playgroud)

该函数testf接受测试类对象 - testobj并用它做事.之后,由于上下文管理器,testcm确保调用清理函数.

所以有两个问题:

  1. 我如何在装饰器中使用上下文管理器,从我所知的装饰器必须返回一个函数,但如果我返回该函数(如上面的代码),上下文管理器将如何调用清理?

  2. 如何将装饰器中创建的对象传递给装饰函数,如果我像上面的代码一样传递它,我将如何调用装饰函数?

python contextmanager python-decorators

3
推荐指数
1
解决办法
508
查看次数

如何在Python中捕获`with open(filename)`引发的异常?

尝试在Python中打开文件的行为会引发异常。如果我使用with语句打开文件,是否可以捕获open调用和相关__enter__调用引发的异常而又不捕获with块中代码引发的异常?

try:
    with open("some_file.txt") as infile:
        print("Pretend I have a bunch of lines here and don't want the `except` below to apply to them")
        # ...a bunch more lines of code here...
except IOError as ioe:
    print("Error opening the file:", ioe)
    # ...do something smart here...
Run Code Online (Sandbox Code Playgroud)

这个问题与这个较老的问题不同,因为这个老问题是关于编写上下文管理器的,而不是使用熟悉的with open

python exception-handling exception contextmanager

3
推荐指数
2
解决办法
2874
查看次数

Getting a context manager created with @contextmanager to work properly with exceptions

I have the following code

from contextlib import contextmanager

@contextmanager
def simple_context_manager():
    print("starting context manager")
    yield
    print("finished context manager")

try:
    with simple_context_manager():
        raise RuntimeError
except RuntimeError:
    print("Caught the error")
print("Moving on")
Run Code Online (Sandbox Code Playgroud)

Right now it prints out

starting context manager
Caught the error
Moving on
Run Code Online (Sandbox Code Playgroud)

which tells me that the context manager isn't closing. How can I get it to close and print the "finished context manager" line?

Since I'm using the decorator, I don't have a dedicated __exit__ function that …

python error-handling contextmanager python-3.x

3
推荐指数
1
解决办法
111
查看次数