首页 > 解决方案 > 手动打开上下文管理器

问题描述

我的问题是,如何在不使用的情况下执行任何上下文管理器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'

来自烧瓶文档

标签: pythonwith-statementcontextmanager

解决方案


您仍然可以with在交互式控制台中使用语法,但是上下文基于 2 个魔术方法__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()

如同:

ctx = MyCtx(foo)
f = ctx.__enter__()
f() 
ctx.__exit__()

这里有活生生的例子

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

__exit__(None, None, None)

推荐阅读