Dieser Code funktioniert nichteinen Kontext-Manager mit einem Koroutine Mit
from contextlib import contextmanager
import tornado.ioloop
import tornado.web
from tornado import gen
from tornado.httpclient import AsyncHTTPClient
@contextmanager
def hello():
print("hello in")
yield
print("hello out")
class MainHandler(tornado.web.RequestHandler):
@gen.coroutine
def get(self):
client = AsyncHTTPClient()
with hello():
result = yield client.fetch("http://localhost")
return "Hello "+str(result)
app = tornado.web.Application([('/', MainHandler)])
app.listen(12345)
tornado.ioloop.IOLoop.current().start()
Und der Grund, warum es nicht funktioniert ist, dass der Kontext-Manager Nachgeben und die Koroutine nachgebend sind in ihrem Verhalten unvereinbar.
Bestätigen Sie, dass der einzige Weg, dies zu erreichen ist, eine try finally
verwenden (besonders ärgerlich, wenn der Context-Manager-Code an vielen Stellen verwendet werden muss). Vielleicht gibt es einen subtilen Trick, von dem ich nichts weiß? Googeln hat nicht geholfen.
bearbeiten
Dies ist die Ausgabe I
(venv) [email protected]:tornado$ python test.py
hello in
ERROR:tornado.application:Uncaught exception GET/(::1)
HTTPServerRequest(protocol='http', host='localhost:12345', method='GET', uri='/', version='HTTP/1.1', remote_ip='::1', headers={'Upgrade-Insecure-Requests': '1', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36', 'Accept-Language': 'en-US,en;q=0.8,it;q=0.6', 'Connection': 'keep-alive', 'Host': 'localhost:12345', 'Accept-Encoding': 'gzip, deflate, sdch'})
Traceback (most recent call last):
File "/Users/sborini/Work/Experiments/tornado/venv/lib/python3.4/site-packages/tornado/web.py", line 1445, in _execute
result = yield result
File "/Users/sborini/Work/Experiments/tornado/venv/lib/python3.4/site-packages/tornado/gen.py", line 1008, in run
value = future.result()
File "/Users/sborini/Work/Experiments/tornado/venv/lib/python3.4/site-packages/tornado/concurrent.py", line 232, in result
raise_exc_info(self._exc_info)
File "<string>", line 3, in raise_exc_info
File "/Users/sborini/Work/Experiments/tornado/venv/lib/python3.4/site-packages/tornado/gen.py", line 1014, in run
yielded = self.gen.throw(*exc_info)
File "test.py", line 20, in get
result = yield client.fetch("http://localhost")
File "/Users/sborini/Work/Experiments/tornado/venv/lib/python3.4/site-packages/tornado/gen.py", line 1008, in run
value = future.result()
File "/Users/sborini/Work/Experiments/tornado/venv/lib/python3.4/site-packages/tornado/concurrent.py", line 232, in result
raise_exc_info(self._exc_info)
File "<string>", line 3, in raise_exc_info
ConnectionRefusedError: [Errno 61] Connection refused
ERROR:tornado.access:500 GET/(::1) 5.04ms
Der Punkt ist, dass ich nie die hello out
Meldung. Ich würde erwarten, dass, sobald fetch
die Zukunft und die zukünftigen Fehler hervorbringt, ich zurück zu der Yield-Point, erhalten Sie die Ausnahme, und verlassen Sie den Kontext, Triggerung der print('hello out')
.
Bitte beachte, dass ich tun hallo, wenn ich nur ein try: finally:
um das zu tun yield
Vermutlich liegt das daran, dass Sie etwas mit "__enter__" und "__exit__" nicht "__aenter__" und "__aexit__" machen. – jonrsharpe
Ich verwende keine Async. Ich bin immer noch auf Python 3.4 mit Vanille Tornado. @jonrsharpe –