标签: contextmanager

Python __enter__/__exit__ vs __init __(或__new__)/ __del__

我已经搜索过了,我无法想出任何使用python的__enter__/ __exit__而不是__init__(或__new__?)/的理由__del__.

我理解__enter__//__exit__旨在与with语句一起用作上下文管理器,with声明很棒.但与此相对应的是,这些块中的任何代码在该上下文中执行.通过使用这些而不是__init__/ __del__我似乎与他们必须使用的调用者创建隐式契约with,但是没有办法强制执行这样的契约,并且合同只通过文档(或阅读代码)传达.这似乎是一个坏主意.

我似乎使用__init__/ __del__with块内部获得相同的效果.但是通过使用它们而不是上下文管理方法,我的对象在其他场景中也很有用.

因此,任何人可以想出为什么我会一个令人信服的理由以往任何时候都需要使用上下文的管理方法,而不是构造函数/析构函数的方法呢?

如果有更好的地方可以提出这样的问题,请告诉我,但似乎没有太多关于此的信息.

跟进:

这个问题是基于一个糟糕的(但可能是常见的)假设,因为我总是习惯于with实例化一个新对象,在这种情况下__init__/__del__非常接近于相同的行为__enter__/__exit__(除非您无法控制何时或是否__del__将被执行,它是直到垃圾收集,如果进程终止,它可能永远不会被调用).但是如果你在with语句中使用预先存在的对象,它们当然是完全不同的.

python constructor destructor with-statement contextmanager

18
推荐指数
2
解决办法
7969
查看次数

使用/作为上下文管理器打开文件列表

注意:我知道

with open('f1') as f1, open('f2') as f2:
    ...
Run Code Online (Sandbox Code Playgroud)

句法.这是一个不同的问题.


给定一个字符串列表file_names有一种方法可以使用with/ as打开每个文件名,使用一行.像这样的东西:

with [open(fn) for fn in file_names] as files:
    # use the list of files
Run Code Online (Sandbox Code Playgroud)

这当然不起作用,因为它试图在列表上使用上下文管理器.在运行时之前可能无法知道列表的长度,例如sys.argv[1:]

python with-statement contextmanager

17
推荐指数
2
解决办法
2446
查看次数

python'with'语句,我应该使用contextlib.closing吗?

from contextlib import closing

def init_db():
    with closing(connect_db()) as db:
        with app.open_resource('schema.sql') as f:
            db.cursor().executescript(f.read())
        db.commit()
Run Code Online (Sandbox Code Playgroud)

这是来自烧瓶教程第3步(http://flask.pocoo.org/docs/tutorial/dbinit/#tutorial-dbinit).我对第4行感到好奇.

我必须导入并使用'contextlib.closing()'方法吗?

当我语句学习,很多文章说它会在下面的过程之后自动关闭文件.(与Last:thing.close()相同)

with open('filename','w') as f:
    f.write(someString);
Run Code Online (Sandbox Code Playgroud)

即使我不使用下面的contextlib.closing(),有什么区别?它来自2.7.6版本,谢谢.

def init_db():
    with connect_db() as db:
        with app.open_resource('schema.sql') as f:
            db.cursor().executescript(f.read())
        db.commit()
Run Code Online (Sandbox Code Playgroud)

python with-statement contextmanager

17
推荐指数
2
解决办法
7441
查看次数

试图用语句和上下文管理器来理解python

我是新手,我只是想了解这个with陈述.我明白它应该替换try/ exceptblock.

现在假设我做了这样的事情:

try:
   name='rubicon'/2 # to raise an exception
except Exception as e:
   print "no not possible"
finally:
   print "Ok I caught you"
Run Code Online (Sandbox Code Playgroud)

如何用上下文管理器替换它?

python contextmanager

16
推荐指数
5
解决办法
9387
查看次数

python如何在上下文管理器中安全地处理异常

我想我已经读过内部异常,with不允许__exit__正确调用.如果我在这个笔记上错了,请原谅我的无知.

所以我在这里有一些伪代码,我的目标是使用锁定上下文,在__enter__记录开始日期时间并返回锁定ID,并在__exit__记录结束日期时间并释放锁定:

def main():
    raise Exception

with cron.lock() as lockid:
    print('Got lock: %i' % lockid)
    main()
Run Code Online (Sandbox Code Playgroud)

除了安全地存在上下文之外,我怎么还能引发错误?

注意:我故意在此伪代码中引发基本异常,因为我想在任何异常时安全退出,而不仅仅是预期的异常.

注意:替代/标准并发防止方法是无关紧要的,我想将这些知识应用于任何一般的上下文管理.我不知道不同的背景是否有不同的怪癖.

PS.该finally块是否相关?

python exception-handling contextmanager

16
推荐指数
2
解决办法
1万
查看次数

处理上下文管理器中的异常

我有一个代码,我尝试访问资源,但有时它不可用,并导致异常.我尝试使用上下文管理器实现重试引擎,但我无法处理__enter__上下文表单上下文管理器中调用者引发的异常.

class retry(object):
    def __init__(self, retries=0):
        self.retries = retries
        self.attempts = 0
    def __enter__(self):
        for _ in range(self.retries):
            try:
                self.attempts += 1
                return self
            except Exception as e:
                err = e
    def __exit__(self, exc_type, exc_val, traceback):
        print 'Attempts', self.attempts
Run Code Online (Sandbox Code Playgroud)

这是一些只引发异常的例子(我希望处理的那个)

>>> with retry(retries=3):
...     print ok
... 
Attempts 1
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
NameError: name 'ok' is not defined
>>> 
>>> with retry(retries=3):
...     open('/file')
... 
Attempts 1
Traceback …
Run Code Online (Sandbox Code Playgroud)

python exception contextmanager

16
推荐指数
4
解决办法
1万
查看次数

Python上下文管理器:有条件地执行主体?

我正在编写一个基于MPI的应用程序(但MPI在我的问题中无关紧要,我只提到它是为了揭示基本原理),在某些情况下,当工作项少于进程时,我需要创建一个新的通信器排除无关的进程.最后,必须通过有工作的流程(并且只有他们)来释放新的沟通者.

一个巧妙的方法是写:

with filter_comm(comm, nworkitems) as newcomm:
    ... do work with communicator newcomm...
Run Code Online (Sandbox Code Playgroud)

正在由有工作的进程执行的正文.

在上下文管理器中有没有办法避免执行正文?我理解上下文管理器的设计是为了避免隐藏控制流,但我想知道是否有可能规避控制流,因为在我的情况下,我认为为了清晰起见,这是合理的.

python contextmanager

15
推荐指数
2
解决办法
1310
查看次数

是否可以访问封闭的上下文管理器?

使用with语句基本上有三种方法:

使用现有的上下文管理器:

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

创建上下文管理器并将其结果绑定到变量:

with Manager() as result:
    pass
Run Code Online (Sandbox Code Playgroud)

创建上下文管理器并丢弃其返回值:

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

如果我们get_manager()在上面的三个块中放置了一个函数,是否有任何实现可以返回封闭的上下文管理器,或者至少它们的__exit__函数?

在第一种情况下,这显然很容易,但我想不出能让它在另外两种情况下工作的方法.我怀疑是否可以获得整个上下文管理器,因为值堆栈会在SETUP_WITH操作码之后立即弹出.但是,由于__exit__函数存储在块堆栈中SETUP_WITH,是否有某种方法可以访问它?

python contextmanager

15
推荐指数
2
解决办法
3072
查看次数

在另一个上下文管理器中处理上下文管理器的实例

如何在Python中处理在另一个上下文管理器中创建的上下文管理器?

示例:假设您具有A充当上下文管理器的类B,以及充当上下文管理器的类.但是类B实例必须实例化并使用类的实例A.我已经通过了PEP 343,这是我想到的解决方案:

class A(object):
    def __enter__(self):
        # Acquire some resources here
        return self

    def __exit__(seplf, exception_type, exception, traceback):
        # Release the resources and clean up
        pass


class B(object):
    def __init__(self):
        self.a = A()

    def __enter__(self):
        # Acquire some resources, but also need to "start" our instance of A
        self.a.__enter__()
        return self

    def __exit__(self, exception_type, exception, traceback):
        # Release the resources, and make our instance of A clean up as well
        self.a.__exit__(exception_type, …
Run Code Online (Sandbox Code Playgroud)

python contextmanager

15
推荐指数
2
解决办法
2699
查看次数

__exit__的返回值

我明白那个

  • __enter____exit__用于实现上下文管理器.

  • 如果with语句中发生异常,则将异常的类型,值和回溯传递给该__exit__方法.

  • __exit__ 可以处理异常:

    1. 返回True:正常处理异常.
    2. 返回任何其他内容:该with语句引发异常

我遇到了以下__exit__方法.return语句是多余的吗?

def __exit__(self, type, value, traceback):
    self.close()
    return type == None
Run Code Online (Sandbox Code Playgroud)

因为在我看来,

  • 如果没有发生异常,type自然会None,所以__exit__返回true.什么都没有提出来.
  • 如果确实发生了异常,type则将其设置为实际的异常类型,因此__exit__返回false.异常是按原样引发的.

python with-statement contextmanager

14
推荐指数
1
解决办法
3782
查看次数