手动打开上下文管理器

时间:2018-08-06 11:42:50

标签: python with-statement contextmanager

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


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

代替

file = open('some_file', 'w')
try:
    file.write('Hola!')
finally:
    file.close()
# end try

您可以写

with open('some_file', 'w') as opened_file:
    opened_file.write('Hola!')
# end with

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

>>> file = open('some_file', 'w')
>>> file.write('Hola!')
>>> file.close()

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


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

import flask

app = flask.Flask(__name__)

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

from flask docs

2 个答案:

答案 0 :(得分:4)

您仍然可以在交互式控制台中使用backend : pro. 语法,但是上下文基于两种魔术方法with__enter__,因此您可以使用它们:

__exit__

通常您这样做:

class MyCtx(object):
  def __init__(self, f):
    self.f = f

  def __enter__(self):
    print("Enter")
    return self.f

  def __exit__(*args, **kwargs):
    print("Exit")

def foo():
  print("Hello")

与:

with MyCtx(foo) as f:
  f()

这里有live example

请记住,上下文ctx = MyCtx(foo) f = ctx.__enter__() f() ctx.__exit__() 方法用于管理上下文中的错误,因此大多数方法都具有__exit__的签名,如果您不需要为测试处理它,只需给它一些__exit__(exception_type, exception_value, traceback)个值:

None

答案 1 :(得分:1)

您可以调用app.test_request.context('/?name=Peter')到变量(例如ctx),然后在其上调用ctx.__enter__()进入上下文管理器,然后ctx.__exit__(None, None, None)进行清理。请注意,除非您将ctx.__exit__放在finally子句中,否则您将失去上下文管理器的安全保证。