采用标准的Tornado演示并将IOLoop推入后台线程,可以在单个脚本中查询服务器。当Tornado服务器是一个交互式对象时(请参阅DASK或类似对象),这很有用。
import asyncio
import requests
import tornado.ioloop
import tornado.web
from concurrent.futures import ThreadPoolExecutor
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
pool = ThreadPoolExecutor(max_workers=2)
loop = tornado.ioloop.IOLoop()
app = make_app()
app.listen(8888)
fut = pool.submit(loop.start)
print(requests.get("https://localhost:8888"))
在标准的python脚本中,上面的代码工作得很好(尽管它缺少安全关闭)。Jupyter笔记本是这些交互式Tornado服务器环境的最佳环境。然而,当涉及到Jupyter时,这个想法就崩溃了,因为已经有一个活动的运行循环:
>>> import asyncio
>>> asyncio.get_event_loop()
<_UnixSelectorEventLoop running=True closed=False debug=False>
当在jupyter笔记本中运行上述脚本时,服务器和请求客户机都试图在同一线程中打开连接,代码挂起。构建一个新的Asyncio循环和/或Tornado IOLoop似乎没有帮助,我怀疑我在Jupyter本身中缺少了一些东西。
问题是:是否可以在Jupyter笔记本的后台运行一个活动的Tornado服务器,以便标准的python
requests
或者类似的可以从主线程连接到它?如果可能的话,我希望避免在向用户提供的代码中使用Asyncio,因为它对于新手用户来说比较复杂。