标签: contextmanager

用于临时变量赋值的 Python 上下文管理器

我经常需要用别的东西临时切换一个变量的值,做一些依赖于这个变量的计算,然后将变量恢复到它的原始值。例如:

var = 0
# Assign temporary value and do computation
var_ori = var
var = 1
do_something_with_var()  # Function that reads the module level var variable
# Reassign original value
var = var_ori
Run Code Online (Sandbox Code Playgroud)

这似乎是使用上下文管理器(with语句)的明显机会。Python 标准库是否包含任何这样的上下文管理器?

编辑

我知道这种事情通常由其他更好的方法处理,而不是临时更改变量。然而,我并不是要求明显的解决方法。

在我的实际工作案例中,我无法更改该do_something_with_var功能。实际上,这甚至不是一个函数,而是作为元编程的一部分在全局命名空间上下文中求值的一串代码。我给出的例子是我能想到的最简单的例子,它使我的问题与临时变量有关。我没有要求获得我的示例代码的解决方法(正确版本),而是要求获得我书面问题的答案。

python with-statement contextmanager python-3.x

9
推荐指数
1
解决办法
3392
查看次数

py.test - 如何在funcarg/fixture中使用上下文管理器

密切相关: 在python中,在setup/teardown中使用上下文管理器是否有一个很好的习惯用法


我有一个上下文管理器,用于测试以修复时间/时区.我想把它放在pytest funcarg(或夹具中,我们使用pytest2.2.3,但我可以向后翻译).我可以这样做:

def pytest_funcarg__fixedTimezone(request):
    # fix timezone to match Qld, no DST to worry about and matches all
    # Eastern states in winter.
    fixedTime = offsetTime.DisplacedRealTime(tz=' Australia/Brisbane')

    def setup():
        fixedTime.__enter__()
        return fixedTime

    def teardown(fixedTime):
        # this seems rather odd?
        fixedTime.__exit__(None, None, None)
Run Code Online (Sandbox Code Playgroud)

......但它有点icky.在相关的问题中,jsbueno指出:问题在于,__exit__如果发生异常,您的代码无法正确调用对象的方法.

他的回答使用了元类方法.但这对pytest来说并不是那么有用,因为pytest通常只是函数,而不是类.那么解决这个问题的方法是什么?什么涉及测试钩

contextmanager pytest

8
推荐指数
2
解决办法
3639
查看次数

在with语句表达式中引发的异常会发生什么?

我对Python with声明的理解如下:

withstatement = with+ expression + as+ target + :+ suit

  1. 执行表达式并返回上下文管理器
  2. 上下文管理器__enter__返回一个目标值
  3. 套件已执行.
  4. __exit__调用上下文管理器的方法

我知道可以在step2和step3中处理异常,我的问题是如果在执行表达式的step1期间抛出异常,我可以获得上下文管理器吗?

如果不是,这是否意味着该with声明只是确保诉讼被正确执行和关闭?

就像with open("file") as f,如果文件不存在会发生什么?

python with-statement contextmanager

8
推荐指数
1
解决办法
128
查看次数

没有Yield的Context Manager

我是否可以拥有一个偶尔不会产生的上下文管理器,在这种情况下,with语句中的代码根本不会被执行?

import contextlib

@contextlib.contextmanager
def MayNotYield(to_yield):
  if to_yield:
    yield

with MayNotYield(True):  
  print 'This works.'

with MayNotYield(False):  
  print 'This errors.'
Run Code Online (Sandbox Code Playgroud)

我可以要求用户使用try-catch包装with语句,但这不是首选.我也可以做以下但它也很难看.

import contextlib

@contextlib.contextmanager
def AlwaysYields(to_yield):
  if to_yield:
    yield 1
  else:
    yield 2

with AlwaysYields(True) as result:
  if result == 1:
    print 'This works.'
Run Code Online (Sandbox Code Playgroud)

python contextmanager

8
推荐指数
2
解决办法
1281
查看次数

Python 中的 Try/Except:如何避免重复?

我有一个类,可以将 API 引发的低级异常转换为高级异常。该类充满了复杂、重复的错误处理逻辑。我正在寻找减少这种重复的Pythonic 方法。

这是一个人为的例子。

class ApiWrapperException(Exception):
  pass

class ApiWrapper(object):

  def __init__(self, api):
    self._api = api

  def do_one_thing(self):
    print 'do_one_thing stuff before API call'
    try:
      self._api.do_one_thing()
    except ApiException:
      print 'ApiWrapper caught an ApiException. Doing complicated error handling logic. Raising a different exception.'
      raise ApiWrapperException
    print 'do_one_thing stuff after API call'

  def do_another_thing(self):
    print 'do_another_thing stuff before API call'
    try:
      self._api.do_another_thing()
    except ApiException:
      print 'ApiWrapper caught an ApiException. Doing complicated error handling logic. Raising a different exception.'
      raise ApiWrapperException
    print 'do_another_thing …
Run Code Online (Sandbox Code Playgroud)

python contextmanager python-decorators

8
推荐指数
1
解决办法
1704
查看次数

嵌套Python上下文管理器

这个问题中,我定义了一个包含上下文管理器的上下文管理器.完成此嵌套最简单的正确方法是什么?我最后打电话来self.temporary_file.__enter__()self.__enter__().但是,self.__exit__我很确定我必须调用self.temporary_file.__exit__(type_, value, traceback)finally块,以防引发异常.如果出现问题,我应该设置type_,value和traceback参数self.__exit__吗?我检查过contextlib,但找不到任何实用程序来帮助解决这个问题.

来自问题的原始代码:

import itertools as it
import tempfile

class WriteOnChangeFile:
    def __init__(self, filename):
        self.filename = filename

    def __enter__(self):
        self.temporary_file = tempfile.TemporaryFile('r+')
        self.f = self.temporary_file.__enter__()
        return self.f

    def __exit__(self, type_, value, traceback):
        try:
            try:
                with open(self.filename, 'r') as real_f:
                    self.f.seek(0)
                    overwrite = any(
                        l != real_l
                        for l, real_l in it.zip_longest(self.f, real_f))
            except IOError:
                overwrite = True
            if overwrite:
                with open(self.filename, 'w') as real_f:
                    self.f.seek(0) …
Run Code Online (Sandbox Code Playgroud)

python contextmanager

7
推荐指数
2
解决办法
2128
查看次数

编写一个只能用作上下文管理器的Python类

有没有办法在Python中编写一个会出错的类,除非它与with语句一起使用?

# Okay:
with Foo() as f1:
    f1.func1()
    f1.func2()

# Not okay:
f2 = Foo()
f2.func1()
Run Code Online (Sandbox Code Playgroud)

我可以手动完成:__enter__设置一个标志并让其他方法检查该标志.但有更好的方法吗?

以下是不那么自然的代码:

class Foo(object):
    def __init__(self):
        self._entered = False

    def __enter__(self):
        self._entered = True
        return self

    def _verify_entered(self):
        if not self._entered:
            raise Exception("Didn't get call to __enter__")

    def __exit__(self, typ, val, traceback):
        self._verify_entered()
        print("In __exit__")

    def func1(self):
        self._verify_entered()
        # do stuff ...

    def func2(self):
        self._verify_entered()
        # do other stuff
Run Code Online (Sandbox Code Playgroud)

python contextmanager

7
推荐指数
1
解决办法
706
查看次数

使用带有 mysql 连接器 python 的上下文管理器

我正在将代码从 sqlite 数据库移动到 mysql,并且上下文管理器出现问题,出现以下属性错误。

我尝试过 mydb.cursor() 作为光标、mydb: 等的组合...



mydb = mysql.connector.connect(
  host="localhost",
  user="root",
  passwd="",
    database="database_name"

cur = mydb.cursor()

Run Code Online (Sandbox Code Playgroud)
with mydb as cursor:
 AttributeError: __enter__
Run Code Online (Sandbox Code Playgroud)

python mysql contextmanager python-3.x

7
推荐指数
2
解决办法
7350
查看次数

有没有办法检测正在运行的代码是否正在上下文管理器内执行?

正如标题所述,有没有办法做到这样的事情:

def call_back():
    if called inside context:
        print("running in context")
    else:
        print("called outside context")
Run Code Online (Sandbox Code Playgroud)

这将导致:

with CTM() as context:
    call_back()
call_back()

>>> "running in context"
>>> "called outside context"
Run Code Online (Sandbox Code Playgroud)

python contextmanager

7
推荐指数
1
解决办法
1159
查看次数

“ except” 语句或上下文管理器中“ as” 绑定的范围是什么?

我知道一般来说 python 只会为类、函数等创建新的作用域,但我对astry/ except 块或上下文管理器中的语句感到困惑。在块内部分配的变量可以在块外部访问,这是有道理的,但是与as则不然。

所以这失败了:

try:
    raise RuntimeError()
except RuntimeError as error:
    pass

print(repr(error))
Run Code Online (Sandbox Code Playgroud)

但这成功了:

try:
    raise RuntimeError()
except RuntimeError as e:
    error = e

print(repr(error))
Run Code Online (Sandbox Code Playgroud)

与 绑定的变量发生了什么as,为什么正常的 python 作用域规则不适用?PEP表明它只是一个正常绑定的 python 变量,但情况似乎并非如此。

python contextmanager

7
推荐指数
2
解决办法
338
查看次数