manually open context manager

十年热恋 提交于 2021-02-04 18:48:09

问题


My question is, how can I execute any context manager without using with?


Python has the idea of context managers,

instead of

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

you can write

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

While in most cases the second one is the golden solution, for testing and exploring in the interactive console, the first one can be much better used, as you can write it line by line.

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

My question is, how can I execute any with context manager like this, best suited for exploring?


My actual use case follows below, but please try to give a answer which is generic and will work for other context managers too.

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


回答1:


You can still use with syntax in the interactive console, however a context is based on 2 magic methods __enter__ and __exit__, so you can just use them:

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")

usually you do:

with MyCtx(foo) as f:
  f()

Same as:

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

Here you have the live example

Remember that contexts __exit__ method are used for managing errors within the context, so most of them have a signature of __exit__(exception_type, exception_value, traceback), if you dont need to handle it for the tests, just give it some None values:

__exit__(None, None, None)



回答2:


You can call app.test_request.context('/?name=Peter') to a variable (e.g. ctx), and then call ctx.__enter__() on it to enter the context manager, and ctx.__exit__(None, None, None) to perform the cleanup. Note that you lose the safety guarantees of context managers, unless you put the ctx.__exit__ in a finally clause.



来源:https://stackoverflow.com/questions/51706836/manually-open-context-manager

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!