# 정책

이벤트 루프 정책은 이벤트 루프의 관리를 제어하는 프로세스별 전역 객체입니다. 각 이벤트 루프는 기본 정책이 있는데, 정책 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())