Python Can';使用协同程序时,无法获得加薪或返回工作岗位
我一直在试验Python 2.7和Tornado 3.2。我一直在尝试使用一个简单的协同程序示例,但运气不佳:Python Can';使用协同程序时,无法获得加薪或返回工作岗位,python,asynchronous,tornado,coroutine,Python,Asynchronous,Tornado,Coroutine,我一直在试验Python 2.7和Tornado 3.2。我一直在尝试使用一个简单的协同程序示例,但运气不佳: import tornado.web from tornado.gen import coroutine from tornado.httpclient import AsyncHTTPClient from tornado.gen import Return class MainHandler(tornado.web.RequestHandler): # Tried wi
import tornado.web
from tornado.gen import coroutine
from tornado.httpclient import AsyncHTTPClient
from tornado.gen import Return
class MainHandler(tornado.web.RequestHandler):
# Tried with and without @asynchronous
@tornado.web.asynchronous
def get(self):
data = MainService().get_google_data()
self.write(data)
class MainService:
@coroutine
def get_google_data(self):
response = yield AsyncHTTPClient().fetch("http://www.google.com")
raise Return(value = 'hello')
我希望在卷曲URL时会写上“hello”。相反,我得到:
...
File "/vagrant/venv/lib/python2.7/site-packages/tornado/web.py", line 656, in write
raise TypeError("write() only accepts bytes, unicode, and dict objects")
TypeError: write() only accepts bytes, unicode, and dict objects
显然,正在返回一个Future,但是对Future调用result()
会引发另一个异常:DummyFuture不支持对结果进行阻塞
Tornado文档说,为了从协同程序返回值,您引发了一个返回异常。看看源代码,这似乎确实是我们所期望的。然而,当我运行它时,它似乎不起作用
感谢您对这方面的任何见解 您需要
产生调用获取谷歌数据()
:
龙卷风协同程序总是返回一个未来
。您可以通过调用yield
来等待Future
的结果。如果没有收益
,您只需立即返回未来
,而无需等待协同程序完成。除了get\u google\u data
之外,您还应该在get
方法上使用@coroutine
装饰器。如果您想使用回调,而不是协同路由,则通常使用@asynchronous
装饰程序。您需要生成获取谷歌数据()的调用。
:
龙卷风协同程序总是返回一个未来
。您可以通过调用yield
来等待Future
的结果。如果没有收益
,您只需立即返回未来
,而无需等待协同程序完成。除了get\u google\u data
之外,您还应该在get
方法上使用@coroutine
装饰器。如果您想使用回调,而不是协同路由,则通常会使用@asynchronous
装饰程序。深入研究Runner.run(),我觉得我可能已经得出了结论。另外,您可以提出Return('hello')
。不需要value=
@dano是的,value=只是没有什么好的理由。深入研究Runner,我现在发现它并不像我第一眼看到的那样。它返回了一个未来,这就是我认为你在回答中所说的。深入研究Runner.run(),我觉得我可能已经对它的作用下了结论。顺便说一句,你可以提高回报('hello')
。不需要value=
@dano是的,value=只是没有什么好的理由。深入研究Runner,我现在发现它并不像我第一眼看到的那样。它返回一个未来,这就是我认为你在回答中所说的。是的,这是有道理的。因此,如果我有一个处理程序来调用一个调用数据访问对象的服务,而数据访问对象实现了一个协同路由,那么堆栈上所有的调用都需要产生并用协同路由进行修饰?@MrSilverSnorkel是的,协同路由通常是“病毒性的”。一旦你添加了一个,所有调用它的东西都想成为一个。有几种方法可以调用协同路由,但实际上调用上下文也不是一个协同路由,但它比“yield coroutine_call()更麻烦一些`。谢谢,你给了我思考的机会。你能给我举一个例子,说明如何在调用上下文不是协同路由的情况下调用协同路由吗?@MrSilverSnorkel第二个和第三个例子展示了调用协同路由http\u client.fetch()的两种方法
来自非协程方法。第二种方法使用纯回调,第三种方法使用连接到未来的回调。再次感谢!非常有用。是的,这很有意义。因此,如果我有一个调用调用数据访问对象的服务的处理程序,并且数据访问对象实现了协程,那么所有调用都会一直到堆栈需要放弃并用协同程序装饰吗?@SilverSnorkel先生是的,协同程序通常是“病毒性”的。一旦你添加了一个,调用它的所有东西都想变成一个。有几种方法可以调用协同程序,而不必实际拥有调用上下文,也可以是一个协同程序,但它比“放弃协同程序”\u call()更笨拙。谢谢,你给了我思考的食物。您能给我举一个例子,说明在调用上下文不是协同路由的情况下调用协同路由的其中一种方法吗?@MrSilverSnorkel第二个和第三个例子展示了从非协同路由方法调用协同路由http\u client.fetch()
的两种方法。第二个使用纯回调,第三个使用连接到Future
的回调。再次感谢!非常有用。
class MainHandler(tornado.web.RequestHandler):
@coroutine
def get(self):
data = yield MainService().get_google_data()
self.write(data)