## **2. 事件循环**
### **2.1. 事件循环函数**
下面这些函数是一些用来访问全局策略的方便的快捷方式。注意,这些函数提供给你访问的是默认策略,除非你在使用这些函数之前使用了set_event_loop_policy()来设置一个替代的策略。
#### asyncio.**get_event_loop**()
   等价于调用`get_event_loop_policy().get_event_loop()`。
#### asyncio.**set_event_loop**(loop)
   等价于调用`get_event_loop_policy().set_event_loop(loop)`。
#### asyncio.**new_event_loop**()
   等价于调用`get_event_loop_policy().new_event_loop()`。
### **2.2. 可用的事件循环**
目前asyncio提供两种事件循环的实现:SelectorEventLoop和ProactorEventLoop。、
#### *class* asyncio.**SelectorEventLoop**
   基于selectors模块的事件循环。是AbstractEventLoop的子类。
   使用当前平台上可用的最高效的selector。
   在Windows上,只有socket相关的被支持(例如:管道不被支持);可以查看[MSDN上的select文档](https://msdn.microsoft.com/en-us/library/windows/desktop/ms740141%28v=vs.85%29.aspx)。
#### *class* asyncio.**SelectorEventLoop**
   Proactor事件循环,使用Windows上的“I/O Completion Ports”(又名IOCP)。是AbstractEventLoop的子类。
   仅在Windows下可用。
> 也可以查阅[MSDN上的I/O Completion Ports文档](https://msdn.microsoft.com/en-us/library/windows/desktop/aa365198%28v=vs.85%29.aspx)。
Windows上使用ProactorEventLoop的实例:
```python
import asyncio, sys
if sys.platform == 'win32':
loop = asyncio.ProactorEventLoop()
asyncio.set_event_loop(loop)
```
### **2.3. 平台支持**
#### **2.3.1. Windows**
Windows事件循环都有的限制:
+ create_unix_connection()和create_unix_server()不被支持:它们的socket family是专供UNIX的socket.AF_UNIX。
+ add_signal_handler()和remove_signal_handler()不被支持。
+ EventLoopPolicy.set_child_watcher()不被支持。ProactorEventLoop支持子进程,它只有一个实施观看的子进程,就没有必要进行配置。
SelectorEventLoop特有的限制:
+ SelectorEventLoop仅支持socket相关,且被限制在512个socket。
+ add_reader()和add_writer()只接受socket的文件描述符。
+ 管道不被支持(例如: connect_read_pipe(), connect_write_pipe())
+ 子进程不被支持(例如:subprocess_exec(), subprocess_shell())
ProactorEventLoop特有的限制:
+ create_datagram_endpoint() (UDP)不被支持。
+ add_reader()和add_writer()不被支持。
在Windows上的单调时钟的分解度通常在15.6毫秒。最佳分解度为0.5毫秒。分解度取决于硬件(HPET的可用性),以及Windows配置。参考asyncio的延时调用。
*改动于3.5版本*:ProactorEventLoop现在支持SSL了。
#### **2.3.2. Mac OS X**
像PTY之类的字符设备,只在Mavericks(Mac OS 10.9)及以上有良好的支持。它们完全不支持Mac OS 10.5或更老的版本。
在Mac OS 10.6, 10.7和10.8上,默认事件循环是使用selectors.KqueueSelector的SelectorEventLoop。selectors.KqueueSelector在这些版本上不支持字符设备。SelectorEventLoop可以在这些版本上使用SelectSelector或者PollSelector来支持字符设备。例如:
```python
import asyncio
import selectors
selector = selectors.SelectSelector()
loop = asyncio.SelectorEventLoop(selector)
asyncio.set_event_loop(loop)
```
### **2.4. 事件循环策略和默认策略**
事件循环管理是策略模式的抽象,来为不同的平台和框架提供最大的灵活性。整个过程的执行,是一个单一的全局策略对象管理着基于可调用上下文的可用进程的事件循环。策略是一个实现了AbstractEventLoopPolicy接口的对象。
对asyncio的大多数用户来说,策略从来不需要明确地处理,因为默认的全局策略就已经足够了。
默认策略的上下文被定义为当前线程,并管理每个与asyncio交互的线程的事件循环。模块级方法get_event_loop()和set_event_loop()提供了能方便地访问通过默认策略管理的事件循环。
### **2.5. 事件循环策略接口**
一个实现循环策略必须实现以下接口:
#### *class* asyncio.**AbstractEventLoopPolicy**
   事件循环策略。
   **get_event_loop**()
      获得当前上下文的事件循环。
      返回一个实现了AbstractEventLoop接口的事件循环对象。
      如果当前上下文没有被设置一个事件循环,且当前策略没有被指定去创建一个,这种情况下会引发一个异常。这个方法绝不会返回`None`。
   **set_event_loop**(loop)
      把当前上下文的事件循环设置为loop。
   **new_event_loop**()
      根据这个策略规则创建并返回一个新的事件循环对象。
      如果没有必要把当前上下文的事件循环设置为这个循环,set_event_loop()方法必须明确地被调用。
### 2.6. **获取全局循环策略**
#### asyncio.**get_event_loop_policy**()
   获取当前事件循环策略。
asyncio.set_event_loop_policy(policy)
   设置当前事件循环策略。如果policy为None,会恢复为默认策略。