mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-01-25 23:11:02 +08:00
校对中
校对中
This commit is contained in:
parent
3591b3559a
commit
dc99a25b11
@ -1,19 +1,17 @@
|
||||
|
||||
# 雾里看花Python之Asyncio
|
||||
# 雾里看花 Python 之 Asyncio
|
||||
|
||||
|
||||
最近我开始发力钻研Python的新[asyncio][4]模块。原因是我需要做一些事情,使用事件IO会使这些事情工作得更好,炙手可热的asynio正好可以用来牛刀小试。从试用的经历来看,该模块比我预想的复杂许多,我现在有足够的信心说,我已经不知道如何恰当地使用asyncio了。
|
||||
最近我开始发力钻研 Python 的新 [asyncio][4] 模块。原因是我需要做一些事情,使用事件 IO 会使这些事情工作得更好,炙手可热的 asynio 正好可以用来牛刀小试。从试用的经历来看,该模块比我预想的复杂许多,我现在有足够的信心说,我已经不知道如何恰当地使用 asyncio 了。
|
||||
|
||||
|
||||
从Twisted框架借鉴一些经验来理解asynio并非难事,但是,asyncio包含众多的元素,我开始动摇,不知道如何将这些孤立的零碎拼图组合成一副完整的图画。我已没有足够的智力提出任何更好的建议,这在里,只想说出我的困惑,求大神指点。
|
||||
从 Twisted 框架借鉴一些经验来理解 asynio 并非难事,但是,asyncio 包含众多的元素,我开始动摇,不知道如何将这些孤立的零碎拼图组合成一副完整的图画。我已没有足够的智力提出任何更好的建议,在这里,只想分享我的困惑,求大神指点。
|
||||
|
||||
|
||||
#### 原语
|
||||
|
||||
*asyncio* 通过<ruby>协程<rt>coroutines</rt></ruby> 辅助来实现异步 IO。最初它是通过 *yield* 和 *yield from* 表达式实现的一个库,因为 Python 语言本身演进的缘故,现在它已经变成一个更复杂的怪兽。所以,为了在同一个频道讨论下去,你需要了解如下一些术语:
|
||||
|
||||
<cite>asyncio</cite>通过coroutines辅助来实现异步IO。最初它是通过<cite>yield</cite>和<cite>yield from</cite>表达式实现的一个库,因为Python语言本身演进的缘故,现在它已经变成一个更复杂的怪兽。所以,为了在同一个频道讨论下去,你需要了解如下一些术语:
|
||||
|
||||
* 事件循环(event loops)
|
||||
* 事件循环(event loops)
|
||||
* 事件循环策略(event loop policies)
|
||||
* awaitables
|
||||
* 协程函数(coroutine function)
|
||||
@ -29,26 +27,25 @@
|
||||
* 传输(transports)
|
||||
* 协议(protocols)
|
||||
|
||||
此外,Python还新增了一些新的特殊方法:
|
||||
* aenter和aexit,用于异步块操作
|
||||
* aiter和anext,用于异步迭代器(异步循环和异步推导)。为了更多的乐趣,协议已经改变一次。 在3.5它返回一个awaitable(协程);在Python 3.6它返回一个新的异步生成器。
|
||||
* await,用于原生的awaitables
|
||||
此外,Python 还新增了一些新的特殊方法:
|
||||
* `__aenter__`和`__aenter__`,用于异步块操作
|
||||
* `__aiter__`和`__anext__ `,用于异步迭代器(异步循环和异步推导)。为了更多的乐趣,协议已经改变一次。 在 Python 3.5 它返回一个awaitable(协程);在 3.6 它返回一个新的异步生成器。
|
||||
* `__await__`,用于自定义的 awaitables
|
||||
|
||||
你还需要了解相当多的内容,文档涵盖了那些部分。尽管如此,我做了一些额外说明以便对其有更好的理解:
|
||||
|
||||
### 事件循环
|
||||
|
||||
|
||||
asyncio事件循环和你第一眼看上去的略有不同。表面看,每个线程都有一个事件循环,然而事实并非如此。我认为他们应该按照如下的方式工作:
|
||||
* 如果是主线程,当调用asyncio.get_event_loop()时创建一个事件循环。
|
||||
* 如果是其他线程,当调用asyncio.get_event_loop()时返回运行时错误。
|
||||
* 当前线程可以使用asyncio.set_event_loop(),在任何时间节点绑定事件循环。该事件循环可由asyncio.new_evet_loop()函数创建。
|
||||
asyncio 事件循环和你第一眼看上去的略有不同。表面看,每个线程都有一个事件循环,然而事实并非如此。我认为他们应该按照如下的方式工作:
|
||||
* 如果是主线程,当调用 asyncio.get_event_loop() 时创建一个事件循环。
|
||||
* 如果是其他线程,当调用 asyncio.get_event_loop() 时返回运行时错误。
|
||||
* 当前线程可以使用 asyncio.set_event_loop(),在任何时间节点绑定事件循环。该事件循环可由 asyncio.new_evet_loop() 函数创建。
|
||||
* 事件循环可以在不绑定到当前线程的情况下使用。
|
||||
* asyncio.get_event_loop()返回绑定线程的事件循环,而非当前运行的事件循环。
|
||||
* asyncio.get_event_loop() 返回绑定线程的事件循环,而非当前运行的事件循环。
|
||||
|
||||
这些行为的组合是超混淆的,主要有以下几个原因。 首先,你需要知道这些函数是全局设置的基础事件循环策略的委托。 默认是将事件循环绑定到线程。 或者,可以在理论上将事件循环绑定到一个greenlet或类似的,如果有人想要的话。 然而,重要的是要知道库代码不控制策略,因此不能推断asyncio将适用于线程。
|
||||
这些行为的组合是超混淆的,主要有以下几个原因。 首先,你需要知道这些函数是全局设置的基础事件循环策略的委托。 默认是将事件循环绑定到线程。 或者,可以在理论上将事件循环绑定到一个 greenlet 或类似的,如果有人想要的话。 然而,重要的是要知道库代码不控制策略,因此不能推断 asyncio 将适用于线程。
|
||||
|
||||
其次,asyncio不需要通过策略将事件循环绑定到上下文。 事件循环可以单独工作。 但是这正是库代码的第一个问题,因为协同程序或类似的东西不知道哪个事件循环负责调度它。 这意味着,如果从协程中调用asyncio.get_event_loop(),你可能得不到运行你的事件循环。 这也是所有API均采用可选的显式事件循环参数的原因。 举例来说,要弄清楚当前哪个协程正在运行,不能使用如下调用:
|
||||
其次,asyncio 不需要通过策略将事件循环绑定到上下文。 事件循环可以单独工作。 但是这正是库代码的第一个问题,因为协同程序或类似的东西不知道哪个事件循环负责调度它。 这意味着,如果从协程中调用 asyncio.get_event_loop(),你可能得不到运行你的事件循环。 这也是所有 API 均采用可选的显式事件循环参数的原因。 举例来说,要弄清楚当前哪个协程正在运行,不能使用如下调用:
|
||||
|
||||
```
|
||||
def get_task():
|
||||
@ -60,7 +57,7 @@ def get_task():
|
||||
|
||||
```
|
||||
|
||||
相反,必须显式地传递事件循环。 这进一步要求你在库代码中显式地遍历事件循环,否则可能发生很奇怪的事情。 我不知道这种设计的思想是什么,但如果不解决这个问题(例如get_event_loop()返回实际运行的事件循环),那么唯一有意义的其他方案是明确禁止显式事件循环传递,并要求它绑定到当前上下文(线程等)。
|
||||
相反,必须显式地传递事件循环。 这进一步要求你在库代码中显式地遍历事件循环,否则可能发生很奇怪的事情。 我不知道这种设计的思想是什么,但如果不解决这个问题(例如get_event_loop() 返回实际运行的事件循环),那么唯一有意义的其他方案是明确禁止显式事件循环传递,并要求它绑定到当前上下文(线程等)。
|
||||
|
||||
由于事件循环策略不提供当前上下文的标识符,因此库也不可能以任何方式“索引”到当前上下文。 也没有回调函数用来监视这样的上下文的拆除,这进一步限制了实际可以开展的操作。
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user