龙卷风的 IOLoop.call_later 行为异常
Tornado's IOLoop.call_later is behaving inexplicably
来自口译员session:
>>>io_loop.call_later(comments_page_delay, functools.partial(http_client.fetch, "google.com", lambda x: print('kek')))
<tornado.ioloop._Timeout object at 0x7fe9a2427b08>
>>> io_loop.start()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.6/site-packages/tornado/ioloop.py", line 755, in start
raise RuntimeError("IOLoop is already running")
RuntimeError: IOLoop is already running
>>> io_loop.call_later(comments_page_delay, functools.partial(http_client.fetch, "google.com", lambda x: print('kek')))
<tornado.ioloop._Timeout object at 0x7fe9a0267808>
>>> io_loop.stop()
>>> io_loop.start()
>>> io_loop.start()
kek
kek
kek
这里:
io_loop = tornado.ioloop.IOLoop.current()
comments_page_delay = 0.1
编辑:
AsyncHTTPClient.configure("tornado.curl_httpclient.CurlAsyncHTTPClient")
http_client = AsyncHTTPClient()
http_client.max_clients = max_clients
http_client.request_timeout = request_timeout
问题:
ioloop 似乎没有 运行 添加了 call_later 的调用。它是 运行ning,正如我尝试执行 io_loop.start() 时出现的错误所证明的那样。为了让它真正执行,我必须先停止循环,然后再启动它两次...非常混乱。
我承认我已经有一段时间没有使用 Tornado 了,但这基本上等同于我知道有效的其他代码。
编辑:代码在第一个 运行 上正常工作,但在连续的 运行 上不能正常工作。此时需要运行io_loop.start()两次returns
这是完整代码(略有删减):
"""...docstring..."""
import functools
import tornado
from tornado.httpclient import AsyncHTTPClient
from lxml import html as lh
from config import comments_page_delay, max_clients, request_timeout
from debug import log
AsyncHTTPClient.configure("tornado.curl_httpclient.CurlAsyncHTTPClient")
http_client = AsyncHTTPClient()
http_client.max_clients = max_clients
http_client.request_timeout = request_timeout
io_loop = tornado.ioloop.IOLoop.current()
def x(y, proxy):
"""...docstring..."""
def handle_response(response):
if response.error:
log('...message...'
.format(uid, response.error), 1)
else:
print('Worked')
data = response.body
comments_url = "...valid url..."
io_loop.call_later(comments_page_delay, functools.partial(http_client.fetch, comments_url, handle_response,
proxy_host=proxy['host'], proxy_port=proxy['port']))
x(1, {'host': None, 'port': None})
io_loop.start()
print('ok')
io_loop.stop()
我在 Emacs python 解释器 session 中 运行 编写代码,如果这在某种程度上是相关的。我会在一秒钟内尝试正常 python session。
EDIT2:如果我 运行 在普通 python 解释器中编写该代码,会发生以下情况:
$ python -i fetch.py
Worked
Traceback (most recent call last):
File "fetch.py", line 34, in <module>
io_loop.start()
File "/usr/lib/python3.6/site-packages/tornado/ioloop.py", line 863, in start
event_pairs = self._impl.poll(poll_timeout)
KeyboardInterrupt
>>> >>> >>> get_user_profile_link(1, {'host': None, 'port': None})
>>>
>>>
>>> io_loop.start()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.6/site-packages/tornado/ioloop.py", line 755, in start
raise RuntimeError("IOLoop is already running")
RuntimeError: IOLoop is already running
>>> io_loop.stop()
>>> io_loop.start()
>>> io_loop.start()
Worked
似乎 io_loop.start() 正在阻塞?我认为不是,这可能是问题所在。我现在必须重新考虑我整个程序的架构。
未捕获的异常(在本例中为 KeyboardInterrupt
)使 IOLoop
处于未定义状态。在发生此类异常后不可能重新启动 IOLoop
(因为它可能随时出现并使 IOLoop
的内部结构不一致)。一般来说,假定进程将在 KeyboardInterrupt
后简单地退出。可以创建一个新的 IOLoop
并从头开始,但是您必须小心地重新创建依赖于它的 all 对象。
不幸的是,这意味着实际上很难将 Tornado 与交互式解释器一起使用。我通常开发 Tornado 应用程序的工作流程是 运行 一个带有 python -m tornado.autoreload
的脚本,每当我编辑它时让脚本重新 运行 从头开始。
来自口译员session:
>>>io_loop.call_later(comments_page_delay, functools.partial(http_client.fetch, "google.com", lambda x: print('kek')))
<tornado.ioloop._Timeout object at 0x7fe9a2427b08>
>>> io_loop.start()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.6/site-packages/tornado/ioloop.py", line 755, in start
raise RuntimeError("IOLoop is already running")
RuntimeError: IOLoop is already running
>>> io_loop.call_later(comments_page_delay, functools.partial(http_client.fetch, "google.com", lambda x: print('kek')))
<tornado.ioloop._Timeout object at 0x7fe9a0267808>
>>> io_loop.stop()
>>> io_loop.start()
>>> io_loop.start()
kek
kek
kek
这里:
io_loop = tornado.ioloop.IOLoop.current()
comments_page_delay = 0.1
编辑:
AsyncHTTPClient.configure("tornado.curl_httpclient.CurlAsyncHTTPClient")
http_client = AsyncHTTPClient()
http_client.max_clients = max_clients
http_client.request_timeout = request_timeout
问题:
ioloop 似乎没有 运行 添加了 call_later 的调用。它是 运行ning,正如我尝试执行 io_loop.start() 时出现的错误所证明的那样。为了让它真正执行,我必须先停止循环,然后再启动它两次...非常混乱。
我承认我已经有一段时间没有使用 Tornado 了,但这基本上等同于我知道有效的其他代码。
编辑:代码在第一个 运行 上正常工作,但在连续的 运行 上不能正常工作。此时需要运行io_loop.start()两次returns
这是完整代码(略有删减):
"""...docstring..."""
import functools
import tornado
from tornado.httpclient import AsyncHTTPClient
from lxml import html as lh
from config import comments_page_delay, max_clients, request_timeout
from debug import log
AsyncHTTPClient.configure("tornado.curl_httpclient.CurlAsyncHTTPClient")
http_client = AsyncHTTPClient()
http_client.max_clients = max_clients
http_client.request_timeout = request_timeout
io_loop = tornado.ioloop.IOLoop.current()
def x(y, proxy):
"""...docstring..."""
def handle_response(response):
if response.error:
log('...message...'
.format(uid, response.error), 1)
else:
print('Worked')
data = response.body
comments_url = "...valid url..."
io_loop.call_later(comments_page_delay, functools.partial(http_client.fetch, comments_url, handle_response,
proxy_host=proxy['host'], proxy_port=proxy['port']))
x(1, {'host': None, 'port': None})
io_loop.start()
print('ok')
io_loop.stop()
我在 Emacs python 解释器 session 中 运行 编写代码,如果这在某种程度上是相关的。我会在一秒钟内尝试正常 python session。
EDIT2:如果我 运行 在普通 python 解释器中编写该代码,会发生以下情况:
$ python -i fetch.py
Worked
Traceback (most recent call last):
File "fetch.py", line 34, in <module>
io_loop.start()
File "/usr/lib/python3.6/site-packages/tornado/ioloop.py", line 863, in start
event_pairs = self._impl.poll(poll_timeout)
KeyboardInterrupt
>>> >>> >>> get_user_profile_link(1, {'host': None, 'port': None})
>>>
>>>
>>> io_loop.start()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.6/site-packages/tornado/ioloop.py", line 755, in start
raise RuntimeError("IOLoop is already running")
RuntimeError: IOLoop is already running
>>> io_loop.stop()
>>> io_loop.start()
>>> io_loop.start()
Worked
似乎 io_loop.start() 正在阻塞?我认为不是,这可能是问题所在。我现在必须重新考虑我整个程序的架构。
未捕获的异常(在本例中为 KeyboardInterrupt
)使 IOLoop
处于未定义状态。在发生此类异常后不可能重新启动 IOLoop
(因为它可能随时出现并使 IOLoop
的内部结构不一致)。一般来说,假定进程将在 KeyboardInterrupt
后简单地退出。可以创建一个新的 IOLoop
并从头开始,但是您必须小心地重新创建依赖于它的 all 对象。
不幸的是,这意味着实际上很难将 Tornado 与交互式解释器一起使用。我通常开发 Tornado 应用程序的工作流程是 运行 一个带有 python -m tornado.autoreload
的脚本,每当我编辑它时让脚本重新 运行 从头开始。