當前位置:
首頁 > 知識 > asyncio让我崩溃

asyncio让我崩溃

箴言

如果实现很难解释,可能不是一个好的实现。

如果实现解释起来很简单,应该是一个不错的实现。

我自己有一个玩具项目,叫“信息流邮件”。它的功能就是抓取我感兴趣的博客和RSS,整合成一封邮件发送给自己。这个工具有用之处就在于它使我不用到处检查社交工具的更新,只在一个地方就能获取所有我感兴趣的信息。

这个工具的实现本身并不困难,只是抓取过程有点慢。我添加的信息源越多,抓取的过程就越慢。

这是async函数的一个完美使用场景。

1

自从我学习了nodejs之后,我就一直想使用一下async函数。我最喜欢的语言还是Python,但有一点nodejs做得更好,就是同时抓取多个api的数据。

asyncio让我崩溃

虽然nodejs做得很好,但是我还是希望能使用Python完成这个工作,因为Python的实现往往更稳定可靠一些。于是我开始查看Python生态圈中是否有一些替代品。

经过一阵研究,我成功地构建了一个简单的demo,它能够在返回页面之前并行地抓取多个URL的内容。

这个小demo确实可用,就是实现方式怪怪的。下面是它的一个极简版。

asyncio让我崩溃

Javascript的运行环境默认是以eventloop的形式运行的,Python下你需要明确地调用event_loop,然后把任务放到event_loop中,直到所有的任务都执行完成。

我对fetch函数的实现感到困惑。在async函数中又写了一个async with语句,这样写很奇怪,为什么要这样写呢?

2

在不写async with的情况下,我又遇到了另外一个奇怪的问题。先展示下这个奇怪的问题的代码:

asyncio让我崩溃

看起来不错,它打开了一个事件循环,放了一些async函数进去,并且等待它们结束以便搜集结果。只有一个问题:运行得还是很慢。

我在.update前后加了日志,发现这些任务其实并不是并行的。它们实际上是一个接一个地串行执行的。

文档中找不到任何解释,大多数StackOverflow的评论也是建议使用async库替代async关键字。代码执行看起来有问题,但是我使用关键字,理论上应该能让代码并行运行才对,不是么?

答案是:需要增加一个sleep调用,休眠时间是0秒。

asyncio让我崩溃

为什么会这样?看起来原因是需要有一些操作使得async函数“暂停然后继续”,才能使gather方法真正地并行运行任务。

在我看来这不可理喻。难道异步函数不应该无论如何都异步运行么?----但是事实就是这样。

3

Armin Ronacher去年写道《我不理解asyncio》。他关注的问题比我的问题更底层,他研究的是线程的机制。我只是想解决一些简单的实现问题。

直到今日,我的高层次的实现,还是比较复杂。这个问题的来源可以追溯到文档的叙述。

协程的文档字符串中这样写道:


“协程”和“生成器”是两个不同但是相关的概念:

  • 定义协程的函数(函数定义时使用了async def关键字,或者用@asyncio.coroutine装饰的函数),我们称之为协程函数(调用iscoroutinefunction()会返回True)。

  • 通过调用一个协程函数得到的对象,我们称之为协程对象(调用iscoroutine()会返回True)。协程对象代表一种最终会完成的计算或者IO操作(通常是两者的结合)。

先生们,文档中的这个解释完全没有说中点子。你不能用猫来解释什么是猫,这不是解释,只是反复复述了几遍罢了。

在文档的同一页,文档展示了这个例子

asyncio让我崩溃

请注意,这里犯了跟我一样的错误:hello_world这个任务实际根本没有异步运行,因为它的代码中没有sleep或者其他什么操作能让当前任务暂停下来,以便后续任务在当前任务还没结束时就启动。如果你想通过这个例子搞清楚Python的异步处理,那么它只会误导你。

4

如果让我完善一下这个文档例子,我会这样写:

asyncio让我崩溃

很赞的是,我上面的例子讲得知识已经足够让我完成我想做的功能了。但是糟糕的是,我不确定这种写法是否就是“真正正确的写法”。当我浏览了太多的文章和博客后,我愈发觉得我知道的很可能都是错的。

翻译

诗书塞外

https://whatisjasongoldstein.com/

writing/im-too-stupid-for-asyncio/

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python部落 的精彩文章:

每位CTO都應該閱讀的十本書
魯班大師,智商250之後的硬傷,是中國製造業的硬傷
探索Python F-strings是如何工作
一个纯python、快速、可扩展的Markdown解释器
月考成绩+NGINX的线程池提升性能9倍!

TAG:Python部落 |