정책
****

이벤트 루프 정책은 이벤트 루프의 관리를 제어하는 프로세스별 전역 객체
입니다. 각 이벤트 루프는 기본 정책이 있는데, 정책 API를 사용하여 변경
하고 사용자 정의할 수 있습니다.

정책은 *컨텍스트*의 개념을 정의하고 컨텍스트마다 별도의 이벤트 루프를
관리합니다. 기본 정책은 *컨텍스트*를 현재 스레드로 정의합니다.

사용자 정의 이벤트 루프 정책을 사용하여, "get_event_loop()",
"set_event_loop()" 및 "new_event_loop()" 함수의 동작을 사용자 정의할
수 있습니다.

정책 객체는 "AbstractEventLoopPolicy" 추상 베이스 클래스에 정의된 API
를 구현해야 합니다.


정책을 얻고 설정하기
====================

다음 함수는 현재 프로세스의 정책을 가져오고 설정하는 데 사용할 수 있습
니다:

asyncio.get_event_loop_policy()

   현재의 프로세스 전반의 정책을 돌려줍니다.

asyncio.set_event_loop_policy(policy)

   현재 프로세스 전반의 정책을 *policy*로 설정합니다.

   *policy*를 "None"으로 설정하면, 기본 정책이 복원됩니다.


정책 객체
=========

추상 이벤트 루프 정책 베이스 클래스는 다음과 같이 정의됩니다:

class asyncio.AbstractEventLoopPolicy

   asyncio 정책의 추상 베이스 클래스.

   get_event_loop()

      현재 컨텍스트의 이벤트 루프를 가져옵니다.

      "AbstractEventLoop" 인터페이스를 구현하는 이벤트 루프 객체를 반
      환합니다.

      이 메서드는 절대 "None"을 반환해서는 안 됩니다.

      버전 3.6에서 변경.

   set_event_loop(loop)

      현재 컨텍스트에 대한 이벤트 루프를 *loop*로 설정합니다.

   new_event_loop()

      새 이벤트 루프 객체를 만들고 반환합니다.

      이 메서드는 절대 "None"을 반환해서는 안 됩니다.

   get_child_watcher()

      자식 프로세스 감시자 객체를 얻습니다.

      "AbstractChildWatcher" 인터페이스를 구현하고 있는 감시자 객체를
      돌려줍니다.

      이 함수는 유닉스 전용입니다.

   set_child_watcher(watcher)

      현재의 자식 프로세스 감시자를 *watcher*로 설정합니다.

      이 함수는 유닉스 전용입니다.

asyncio에는 다음과 같은 내장 정책이 제공됩니다:

class asyncio.DefaultEventLoopPolicy

   기본 asyncio 정책. 유닉스와 윈도우 플랫폼 모두에서
   "SelectorEventLoop"를 사용합니다.

   수동으로 기본 정책을 설치할 필요는 없습니다. asyncio는 기본 정책을
   자동으로 사용하도록 구성됩니다.

class asyncio.WindowsProactorEventLoopPolicy

   "ProactorEventLoop" 이벤트 루프 구현을 사용하는 대안 이벤트 루프 정
   책.

   가용성: 윈도우.


프로세스 감시자
===============

프로세스 감시자는 이벤트 루프가 유닉스에서 자식 프로세스를 관찰하는 방
법을 사용자 정의할 수 있도록 합니다. 특히, 이벤트 루프는 자식 프로세스
가 언제 종료했는지 알 필요가 있습니다.

asyncio에서, 자식 프로세스는 "create_subprocess_exec()" 와
"loop.subprocess_exec()" 함수로 만들어집니다.

asyncio는 자식 관찰자가 구현해야 하는 "AbstractChildWatcher" 추상 베이
스 클래스를 정의하며, "SafeChildWatcher"(기본적으로 사용하도록 구성됩
니다)와 "FastChildWatcher"의 두 가지 구현이 있습니다.

서브 프로세스와 스레드 절도 참조하십시오.

다음 두 함수를 사용하여 asyncio 이벤트 루프에서 사용되는 자식 프로세스
감시자 구현을 사용자 정의할 수 있습니다:

asyncio.get_child_watcher()

   현재 정책에 대한 현재 자식 감시자를 반환합니다.

asyncio.set_child_watcher(watcher)

   현재 정책에 대한 현재 자식 관찰자를 *watcher*로 설정합니다.
   *watcher*는 "AbstractChildWatcher" 베이스 클래스에 정의된 메서드를
   구현해야 합니다.

참고:

  제삼자 이벤트 루프 구현은 사용자 정의 자식 관찰자를 지원하지 않을 수
  있습니다. 이러한 이벤트 루프에서는, "set_child_watcher()" 사용은 금
  지되거나 효과가 없습니다.

class asyncio.AbstractChildWatcher

   add_child_handler(pid, callback, *args)

      새로운 자식 처리기를 등록합니다.

      PID가 *pid* 인 프로세스가 종료할 때 "callback(pid, returncode,
      *args)"가 호출되도록 배치합니다. 같은 프로세스에 대해 다른 콜백
      을 지정하면 이전 처리기가 교체됩니다.

      *callback* 콜러블은 스레드 안전해야 합니다.

   remove_child_handler(pid)

      PID가 *pid* 인 프로세스의 처리기를 제거합니다.

      이 함수는 처리기가 성공적으로 제거되면 "True"를, 제거할 것이 없
      으면 "False"를 반환합니다.

   attach_loop(loop)

      감시자를 이벤트 루프에 연결합니다.

      감시자가 이전에 이벤트 루프에 연결되었으면, 새 루프에 연결하기
      전에 먼저 제거됩니다.

      참고: loop는 "None" 일 수 있습니다.

   close()

      감시자를 닫습니다.

      이 메서드는 하부 자원을 정리하기 위해 호출해야 합니다.

class asyncio.SafeChildWatcher

   이 구현은 "SIGCHLD" 시그널에 대해 명시적으로 모든 프로세스를 폴링하
   여 프로세스를 스포닝하는 다른 코드를 방해하지 않습니다.

   이것은 안전한 해법이지만 많은 수의 프로세스를 처리할 때 상당한 오버
   헤드가 있습니다 ("SIGCHLD"가 수신될 때마다 *O(n)*).

   asyncio는 기본적으로 이 안전한 구현을 사용합니다.

class asyncio.FastChildWatcher

   이 구현은 "os.waitpid(-1)"를 직접 호출하여 종료된 모든 프로세스를
   거둡니다. 프로세스를 스포닝하는 다른 코드를 망가뜨리고 그들의 종료
   를 기다릴 수 있습니다.

   많은 수의 자식을 처리할 때 눈에 띄는 오버헤드가 없습니다 (자식이 종
   료될 때마다 *O(1)*).


사용자 정의 정책
================

새로운 이벤트 루프 정책을 구현하려면, "DefaultEventLoopPolicy"의 서브
클래스를 만들고 사용자 정의 동작이 필요한 메서드를 재정의하는 것이 좋
습니다, 예를 들어:

   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())
