【发布时间】:2016-03-19 13:47:39
【问题描述】:
我之前在 Python 中玩过线程,但决定尝试 asyncio 模块,特别是因为您可以取消正在运行的任务,这似乎是一个不错的细节。但是,由于某种原因,我无法理解它。
这是我想要实现的(抱歉,如果我使用了不正确的术语):
-
downloader线程每 x 秒下载同一个文件,检查其哈希值是否与之前下载的内容不同,如果不同则保存。 - 在后台运行的
webserver线程,允许控制(暂停、列出、停止)downloader线程。
我使用aiohttp 作为网络服务器。
这是我目前所拥有的:
class aiotest():
def __init__(self):
self._dl = None # downloader future
self._webapp = None # web server future
self.init_server()
def init_server(self):
print('Setting up web interface')
app = web.Application()
app.router.add_route('GET', '/stop', self.stop)
print('added urls')
self._webapp = app
@asyncio.coroutine
def _downloader(self):
while True:
try:
print('Downloading and verifying file...')
# Dummy sleep - to be replaced by actual code
yield from asyncio.sleep(random.randint(3,10))
# Wait a predefined nr of seconds between downloads
yield from asyncio.sleep(30)
except asyncio.CancelledError:
break
@asyncio.coroutine
def _supervisor(self):
print('Starting downloader')
self._dl = asyncio.async(self._downloader())
def start(self):
loop = asyncio.get_event_loop()
loop.run_until_complete(self._supervisor())
loop.close()
@asyncio.coroutine
def stop(self):
print('Received STOP')
self._dl.cancel()
return web.Response(body=b"Stopping... ")
这个类被调用:
t = aiotest()
t.start()
这当然行不通,我觉得这是一段可怕的代码。
我不清楚的地方:
- 我在
stop()方法中停止了downloader,但是我将如何停止网络服务器(例如在shutdown()方法中)? -
downloader是否需要新的事件循环,或者我可以使用asyncio.get_event_loop()返回的循环吗? - 我真的需要像
supervisor这样的东西来实现我想要实现的功能吗?这看起来很笨拙。我如何让supervisor继续运行,而不是像现在这样在单次执行后结束?
最后一个更普遍的问题:asyncio 是否应该取代threading 模块(将来)?还是每个都有自己的应用程序?
感谢所有的指点、评论和澄清!
【问题讨论】:
-
您的
downloader是否像在传统线程中那样阻塞?还是会使用所有异步调用? -
@cpburnz 我最初使用了
requests(如果我没看错的话会阻塞),但也可以使用aiohttp。它不会下载多个文件(只下载一个),而且文件本身相对较小( -
@Kristof 你有任何关于答案的问题吗?随时问。
-
@germn 你真的帮了我很多,我在
asyncio上做了很多阅读,慢慢开始掌握它。非常感谢您花时间重写我的代码!
标签: python python-3.x python-asyncio