# 18.5.2. イベントループ

ソースコード: Lib/asyncio/events.py

## 18.5.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()` の呼び出しと等価です。

## 18.5.2.2. 利用可能なイベントループ

asyncio は現在 2 種類の実装のイベントループ、`SelectorEventLoop` と `ProactorEventLoop` を提供しています。

class `asyncio.``SelectorEventLoop`

  `selectors` モジュールベースのイベントループで、`AbstractEventLoop` のサブクラスです。

  プラットフォームで利用できる最も効率的なセレクターを使用します。

  Windows ではソケットのみサポートされています (例えばパイプは未サポート): MSDN の select のドキュメント を参照してください。

class `asyncio.``ProactorEventLoop`

  "I/O Completion Ports" (IOCP) を使用した Windows 用のプロアクターイベントループで、`AbstractEventLoop` のサブクラスです。

  利用できる環境 : Windows.

  参考

  MSDN の I/O Completion Ports のドキュメント。

Windows で `ProactorEventLoop` を使用した例:

    import asyncio, sys

    if sys.platform == 'win32':
        loop = asyncio.ProactorEventLoop()
        asyncio.set_event_loop(loop)

## 18.5.2.3. プラットフォームでのサポート

`asyncio` モジュールは移植性を考慮して設計されていますが、プラットフォームごとにわずかな違いがあり、`asyncio` の全機能をサポートしているわけではありません。

### 18.5.2.3.1. Windows

Windows のイベントループでの共通の制限:

- `create_unix_connection()` および `create_unix_server()` はサポートされていません: ソケットファミリー `socket.AF_UNIX` は UNIX 固有です

- `add_signal_handler()` と `remove_signal_handler()` はサポートされていません

- `EventLoopPolicy.set_child_watcher()` は未サポート: `ProactorEventLoop` はサブプロセスをサポートします。これは子プロセスを監視できる唯一の実装で、構成設定を必要としません。

`SelectorEventLoop` 固有の制限:

- `SelectSelector` が使用されるがサポートしているのはソケットのみで 512 ソケットに制限される

- `add_reader()` および `add_writer()` はソケットのファイル記述子受け取るだけです

- パイプは未サポート (例: `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 をサポートしました。

### 18.5.2.3.2. Mac OS X

PTY のようなキャラクターデバイスは Mavericks (Mac OS 10.9) 以降でのみ十分サポートされています。Mac OS 10.5 以前ではサポートされていません。

Mac OS 10.6、10.7 および 10.8 では、デフォルトのイベントループは `SelectorEventLoop` で、`selectors.KqueueSelector` を使用します。`selectors.KqueueSelector` はこれらのバージョンではキャラクターデバイスをサポートしていません。これらのバージョンでキャラクターデバイスをサポートするには `SelectorEventLoop` で `SelectSelector` または `PollSelector` を使用します。例:

    import asyncio
    import selectors

    selector = selectors.SelectSelector()
    loop = asyncio.SelectorEventLoop(selector)
    asyncio.set_event_loop(loop)

## 18.5.2.4. イベントループのポリシーとデフォルトポリシー

イベントループの管理は、カスタムプラットフォームやフレームワークのために最大限の柔軟性を提供するため ポリシー パターンによって抽象化されます。プロセスの実行中、単一のポリシーオブジェクトが、コンテキスト呼び出しベースのプロセスから利用可能なイベントループを管理します。一つのポリシーは一つの `AbstractEventLoopPolicy` インターフェースを実装するオブジェクトです。

For most users of `asyncio`, policies never have to be dealt with explicitly, since the default global policy is sufficient (see below).

The module-level functions `get_event_loop()` and `set_event_loop()` provide convenient access to event loops managed by the default policy.

## 18.5.2.5. イベントループポリシーインターフェース

イベントループのポリシーは以下のインターフェースを実装しなければなりません:

class `asyncio.``AbstractEventLoopPolicy`

  イベントループポリシーです。

  `get_event_loop`()

    現在のコンテクストのイベントループを取得します。

    Returns an event loop object implementing the `AbstractEventLoop` interface. In case called from coroutine, it returns the currently running event loop.

    現在のコンテキストに設定されているイベントループが存在しない場合やイベントループを作成するためのポリシーが指定されていない場合には例外を送出します。 `None` を返すことがあってはなりません。

    バージョン 3.6 で変更.

  `set_event_loop`(loop)

    現在のコンテキストにイベントループ loop を設定します。

  `new_event_loop`()

    このポリシーのルールに従った新しいイベントループを作成して返します。

    このループを現在のコンテキストのイベントループとして設定する必要がある場合は、`set_event_loop()` が明示的に呼び出されなくてはなりません。

The default policy defines context as the current thread, and manages an event loop per thread that interacts with `asyncio`. If the current thread doesn't already have an event loop associated with it, the default policy's `get_event_loop()` method creates one when called from the main thread, but raises `RuntimeError` otherwise.

## 18.5.2.6. グローバルループポリシーへのアクセス

`asyncio.``get_event_loop_policy`()

  現在のイベントループポリシーを取得します。

`asyncio.``set_event_loop_policy`(policy)

  現在のイベントループポリシーを設定します。policy が `None` の場合、デフォルトポリシーが復元されます。

## 18.5.2.7. Customizing the event loop policy

To implement a new event loop policy, it is recommended you subclass the concrete default event loop policy `DefaultEventLoopPolicy` and override the methods for which you want to change behavior, for example:

    class MyEventLoopPolicy(asyncio.DefaultEventLoopPolicy):

        def get_event_loop(self):
            """Get the event loop.

            This may be None or an instance of EventLoop.
            """
            loop = super().get_event_loop()
            # Do something with loop ...
            return loop

    asyncio.set_event_loop_policy(MyEventLoopPolicy())