代码之家  ›  专栏  ›  技术社区  ›  luckydonald

手动打开上下文管理器

  •  2
  • luckydonald  · 技术社区  · 6 年前

    我的问题是,如果不使用 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()
    

    我的问题是,我怎么能执行任何 具有 这样的上下文管理器,最适合探索?


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

    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 回复  |  直到 6 年前
        1
  •  4
  •   Netwave    6 年前

    你还可以用 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()
    

    等同于:

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

    给你这个 live example

    记住上下文 第二代 方法用于管理上下文中的错误,因此大多数方法都具有 __exit__(exception_type, exception_value, traceback) ,如果你不需要为考试做准备,就给它一些 None 价值观:

    __exit__(None, None, None)
    
        2
  •  1
  •   L3viathan gboffi    6 年前

    你可以打电话 app.test_request.context('/?name=Peter') 变量(例如。 ctx ),然后打电话 ctx.__enter__() 输入上下文管理器,然后 ctx.__exit__(None, None, None) 进行清理。注意,您失去了上下文管理器的安全保证,除非您将 ctx.__exit__ 在一个 finally 条款。