Loop de Eventos
***************

-[ Prefácio ]-

O loop de eventos é o núcleo de toda aplicação asyncio. Loops de
evento executam tarefas e callbacks assíncronos, realizam operações de
entrada e saída e executam subprocessos.

Os desenvolvedores de aplicação normalmente devem usar as funções
asyncio de alto nível, como "asyncio.run()", e devem raramente
precisar fazer referência ao objeto de loop ou chamar seus métodos.
Esta seção destina-se principalmente a autores de código de baixo
nível, bibliotecas e frameworks, que precisam de um controle mais
preciso sobre o comportamento do laço de evento.

-[ Obtendo o Loop de Eventos ]-

As seguintes funções baixo nível podem ser usadas para obter, definir,
ou criar um laço de eventos:

asyncio.get_running_loop()

   Retorna o laço de eventos em execução na thread atual do sistema
   operacional.

   Se não existir nenhum laço de eventos em execução, um
   "RuntimeError" é levantado. Esta função somente pode ser chamada a
   partir de uma corrotina ou uma função de retorno.

   Novo na versão 3.7.

asyncio.get_event_loop()

   Obtém o laço de eventos atual.

   Se não existe nenhum laço de eventos definido na thread atual do
   sistema operacional, é a thread principal do sistema operacional, e
   "set_event_loop()" ainda não foi chamada, asyncio irá criar um novo
   laço de eventos e defini-lo como o atual.

   Devido ao fato desta função ter um comportamento particularmente
   complexo (especialmente quando políticas de laço de eventos
   customizadas estão sendo usadas), usar a função
   "get_running_loop()" é preferido ao invés de "get_event_loop()" em
   corrotinas e funções de retorno.

   Considere também usar a função "asyncio.run()" ao invés de usar
   funções de baixo nível para manualmente criar e fechar um laço de
   eventos.

asyncio.set_event_loop(loop)

   Define *loop* como o laço de eventos atual para a thread atual do
   sistema operacional.

asyncio.new_event_loop()

   Cria um novo objeto de laço de eventos.

Perceba que o comportamento das funções "get_event_loop()",
"set_event_loop()", e "new_event_loop()" podem ser alteradas definindo
uma política de laço de eventos customizada.

-[ Conteúdo ]-

Esta página de documentação contém as seguintes seções:

* A seção Métodos do laço de eventos é a documentação de referência
  das APIs de laço de eventos;

* A seção Tratadores de função de retorno documenta as instâncias das
  classes "Handle" e "TimerHandle", que são retornadas por métodos de
  agendamento tais como "loop.call_soon()" e "loop.call_later()";

* A seção Objetos Server documenta tipos retornados a partir de
  métodos de laço de eventos, como "loop.create_server()";

* A seção Implementações do Laço de Eventos documenta as classes
  "SelectorEventLoop" e "ProactorEventLoop";

* A seção Exemplos demonstra como trabalhar com algumas APIs do laço
  de eventos APIs.


Métodos do laço de eventos
==========================

Laços de eventos possuem APIs de **baixo nível** para as seguintes
situações:

* Executar e interromper o laço

* Agendando funções de retorno

* Agendando funções de retorno atrasadas

* Criando Futures e Tasks

* Abrindo conexões de rede

* Criando servidores de rede

* Transferindo arquivos

* Atualizando TLS

* Observando descritores de arquivo

* Trabalhando com objetos soquete diretamente

* DNS

* Trabalhando com encadeamentos

* Sinais Unix

* Executando código em conjuntos de threads ou processos

* Tratando erros da API

* Habilitando o modo de debug

* Executando Subprocessos


Executar e interromper o laço
-----------------------------

loop.run_until_complete(future)

   Executar até que o *future* (uma instância da classe "Future") seja
   completada.

   Se o argumento é um objeto corrotina, ele é implicitamente agendado
   para executar como uma "asyncio.Task".

   Retorna o resultado do Future ou levanta sua exceção.

loop.run_forever()

   Executa o laço de eventos até que "stop()" seja chamado.

   Se "stop()" for chamado antes que "run_forever()" seja chamado, o
   laço  irá pesquisar o seletor de E/S uma vez com um tempo limite de
   zero, executar todas as funções de retorno agendadas na resposta de
   eventos de E/S (e aqueles que já estavam agendados), e então sair.

   Se "stop()" for chamado enquanto "run_forever()" estiver
   executando, o laço irá executar o lote atual de funções de retorno
   e então sair. Perceba que novas funções de retorno agendadas por
   funções de retorno não serão executadas neste caso; ao invés disso,
   elas serão executadas na próxima vez que "run_forever()" ou
   "run_until_complete()" forem chamadas.

loop.stop()

   Para o laço de eventos.

loop.is_running()

   Retorna "True" se o laço de eventos estiver em execução.

loop.is_closed()

   Retorna "True" se o laço de eventos foi fechado.

loop.close()

   Fecha o loop de eventos.

   O laço não deve estar em execução quando esta função for chamada.
   Qualquer função de retorno pendente será descartada.

   Este método limpa todas as filas e desliga o executor, mas não
   aguarda pelo encerramento do executor.

   Este método é idempotente e irreversível. Nenhum outro método deve
   ser chamado depois que o laço de eventos esteja fechado.

coroutine loop.shutdown_asyncgens()

   Agenda todos os objetos *geradores assíncronos* atualmente abertos
   para serem fechados com uma chamada "aclose()". Após chamar este
   método, o laço de eventos emitirá um aviso se um novo gerador
   assíncrono for iterado. Isso deve ser utilizado para finalizar  de
   forma confiável todos os geradores assíncronos agendados.

   Perceba que não é necessário chamar esta função quando
   "asyncio.run()" for usado.

   Exemplo:

      try:
          loop.run_forever()
      finally:
          loop.run_until_complete(loop.shutdown_asyncgens())
          loop.close()

   Novo na versão 3.6.


Agendando funções de retorno
----------------------------

loop.call_soon(callback, *args, context=None)

   Schedule a *callback* to be called with *args* arguments at the
   next iteration of the event loop.

   Funções de retorno são chamadas na ordem em que elas foram
   registradas. Cada função de retorno será chamada exatamente uma
   vez.

   Um argumento opcional somente-nomeado *context* permite especificar
   um "contextvars.Context" customizado para executar na *função de
   retorno*. O contexto atual é usado quando nenhum *context* é
   fornecido.

   Uma instância de "asyncio.Handle" é retornado, o qual pode ser
   usado posteriormente para cancelar a função de retorno.

   Este método não é seguro para thread.

loop.call_soon_threadsafe(callback, *args, context=None)

   Uma variante segura para thread do "call_soon()". Deve ser usada
   para agendar funções de retorno *a partir de outra thread*.

   Veja a seção concorrência e multithreading da documentação.

Alterado na versão 3.7: O parâmetro somente-nomeado *context* foi
adicionado. Veja **PEP 567** para mais detalhes.

Nota:

  Maior parte das funções de agendamento "asyncio" não permite passar
  argumentos nomeados. Para fazer isso, use "functools.partial()":

     # will schedule "print("Hello", flush=True)"
     loop.call_soon(
         functools.partial(print, "Hello", flush=True))

  Usar objetos parciais é usualmente mais conveniente que usar
  lambdas, pois asyncio pode renderizar objetos parciais melhor
  durante debug e mensagens de erro.


Agendando funções de retorno atrasadas
--------------------------------------

Laço de eventos fornece mecanismos para agendar funções de retorno
para serem chamadas em algum ponto no futuro. Laço de eventos usa
relógios monotônico para acompanhar o tempo.

loop.call_later(delay, callback, *args, context=None)

   Agenda *callback* para ser chamada após o *delay* número de
   segundos fornecido (pode ser um inteiro ou um ponto flutuante).

   Uma instância de "asyncio.TimerHandle" é retornada, a qual pode ser
   usada para cancelar a função de retorno.

   *callback* será chamada exatamente uma vez. Se duas funções de
   retorno são agendadas para exatamente o mesmo tempo, a ordem na
   qual elas são chamadas é indefinida.

   O *args* posicional opcional será passado para a função de retorno
   quando ela for chamada. Se você quiser que a função de retorno seja
   chamada com argumentos nomeados, use "functools.partial()".

   Um argumento opcional somente-nomeado *context* permite especificar
   um "contextvars.Context" customizado para executar na *função de
   retorno*. O contexto atual é usado quando nenhum *context* é
   fornecido.

   Alterado na versão 3.7: O parâmetro somente-nomeado *context* foi
   adicionado. Veja **PEP 567** para mais detalhes.

   Alterado na versão 3.7.1: In Python 3.7.0 and earlier with the
   default event loop implementation, the *delay* could not exceed one
   day. This has been fixed in Python 3.7.1.

loop.call_at(when, callback, *args, context=None)

   Agenda *callback* para ser chamada no timestamp absoluto fornecido
   *when* (um inteiro ou um ponto flutuante), usando o mesmo horário
   de referência que "loop.time()".

   O comportamento deste método é o mesmo que "call_later()".

   Uma instância de "asyncio.TimerHandle" é retornada, a qual pode ser
   usada para cancelar a função de retorno.

   Alterado na versão 3.7: O parâmetro somente-nomeado *context* foi
   adicionado. Veja **PEP 567** para mais detalhes.

   Alterado na versão 3.7.1: In Python 3.7.0 and earlier with the
   default event loop implementation, the difference between *when*
   and the current time could not exceed one day.  This has been fixed
   in Python 3.7.1.

loop.time()

   Retorna o horário atual, como um valor "float", de acordo com o
   relógio monotônico interno do laço de eventos.

Nota:

  Alterado na versão 3.8: No Python 3.7 e anterior, tempos limites
  (*delay* relativo ou *when* absoluto) não poderiam exceder um dia.
  Isto foi ajustado no Python 3.8.

Ver também: A função "asyncio.sleep()".


Criando Futures e Tasks
-----------------------

loop.create_future()

   Cria um objeto "asyncio.Future" atachado ao laço de eventos.

   Este é o modo preferido para criar Futures em asyncio. Isto permite
   que laços de eventos de terceiros forneçam implementações
   alternativas do objeto Future (com melhor desempenho ou
   instrumentação).

   Novo na versão 3.5.2.

loop.create_task(coro)

   Agenda a execução de uma Coroutines. Retorna um objeto "Task".

   Laços de eventos de terceiros podem usar suas próprias subclasses
   de "Task" para interoperabilidade. Neste caso, o tipo do resultado
   é uma subclasse de "Task".

loop.set_task_factory(factory)

   Define a factory da tarefa que será usada por "loop.create_task()".

   Se *factory* for "None", a factory da task padrão será definida.
   Caso contrário, *factory* deve ser algo *chamável* com a assinatura
   coincidindo com "(loop, coro)", onde *loop* é uma referência para o
   laço de eventos ativo, e *coro* é um objeto corrotina. O objeto
   chamável deve retornar um objeto compatível com "asyncio.Future".

loop.get_task_factory()

   Retorna uma factory de tarefa ou "None" se a factory padrão estiver
   em uso.


Abrindo conexões de rede
------------------------

coroutine loop.create_connection(protocol_factory, host=None, port=None, *, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None, ssl_handshake_timeout=None)

   Abre uma conexão de transporte para streaming, para um endereço
   fornecido, especificado por *host* e *port*.

   A família de soquetes pode ser "AF_INET" ou "AF_INET6" dependendo
   do *host* (ou do argumento *family*, se fornecido).

   O tipo de soquete será "SOCK_STREAM".

   *protocol_factory* deve ser um chamável que retorne uma
   implementação do protocolo asyncio.

   Este método tentará estabelecer a conexão em segundo plano. Quando
   tiver sucesso, ele retorna um par "(transport, protocol)".

   A sinopse cronológica da operação subjacente é conforme abaixo:

   1. A conexão é estabelecida e um transporte é criado para ela.

   2. *protocol_factory* é chamada sem argumentos e é esperada que
      retorne uma instância de protocolo.

   3. A instância de protocolo é acoplada com o transporte, através da
      chamada do seu método "connection_made()".

   4. Uma tupla "(transport, protocol)" é retornada ao ter sucesso.

   O transporte criado é um stream bi-direcional dependente de
   implementação.

   Outros argumentos:

   * *ssl*: se fornecido e não for falso, um transporte SSL/TLS é
     criado (por padrão um transporte TCP simples é criado). Se *ssl*
     for um objeto "ssl.SSLContext", este contexto é usado para criar
     o transporte; se *ssl* for "True", um contexto padrão retornado
     de "ssl.create_default_context()" é usado.

     Ver também: SSL/TLS security considerations

   * *server_hostname* define ou substitui o hostname que o
     certificado do servidor de destino será pareado contra. Deve ser
     passado apenas se *ssl* não for "None". Por padrão o valor do
     argumento *host* é usado. Se *host* for vazio, não existe valor
     padrão e você deve passar um valor para *server_hostname*. Se
     *server_hostname* for uma string vazia, o pareamento de hostname
     é desabilitado (o que é um risco de segurança sério, permitindo
     ataques potenciais man-in-the-middle).

   * *family*, *proto*, *flags* são os endereços familiares,
     protocolos e sinalizadores opcionais a serem passados por
     getaddrinfo() para resolução do *host*. Se fornecidos, eles devem
     ser todos inteiros e constantes correspondentes do módulo
     "socket".

   * *sock*, if given, should be an existing, already connected
     "socket.socket" object to be used by the transport. If *sock* is
     given, none of *host*, *port*, *family*, *proto*, *flags* and
     *local_addr* should be specified.

   * *local_addr*, if given, is a "(local_host, local_port)" tuple
     used to bind the socket to locally.  The *local_host* and
     *local_port* are looked up using "getaddrinfo()", similarly to
     *host* and *port*.

   * *ssl_handshake_timeout* é (para uma conexão TLS) o tempo em
     segundos para aguardar pelo encerramento do aperto de mão TLS,
     antes de abortar a conexão. "60.0" segundos se for``None`` (valor
     padrão).

   Novo na versão 3.7: O parâmetro *ssl_handshake_timeout*.

   Alterado na versão 3.6: A opção de soquete "TCP_NODELAY" é definida
   por padrão para todas as conexões TCP.

   Alterado na versão 3.5: Adicionado suporte para SSL/TLS na
   "ProactorEventLoop".

   Ver também:

     A função "open_connection()" é uma API alternativa de alto nível.
     Ela retorna um par de ("StreamReader", "StreamWriter") que pode
     ser usado diretamente em código async/await.

coroutine loop.create_datagram_endpoint(protocol_factory, local_addr=None, remote_addr=None, *, family=0, proto=0, flags=0, reuse_address=None, reuse_port=None, allow_broadcast=None, sock=None)

   Nota:

     O parâmetro *reuse_address* não é mais suportado, assim como usar
     "SO_REUSEADDR" representa uma preocupação de segurança
     significativa para UDP. Passar "reuse_address=True"
     explicitamente irá levantar uma exceção.When multiple processes
     with differing UIDs assign sockets to an indentical UDP socket
     address with "SO_REUSEADDR", incoming packets can become randomly
     distributed among the sockets.Para plataformas suportadas,
     *reuse_port* pode ser usado como um substituto para
     funcionalidades similares. Com *reuse_port*, "SO_REUSEPORT" é
     usado ao invés, o qual especificamente previne processos com
     diferentes UIDs de atribuir soquetes para o mesmo endereço do
     soquete.

   Cria uma conexão de datagrama.

   A família de soquetes pode ser "AF_INET", "AF_INET6", ou "AF_UNIX",
   dependendo do *host* (ou do argumento *family*, se fornecido).

   O tipo de soquete será "SOCK_DGRAM".

   *protocol_factory* deve ser algo chamável, retornando uma
   implementação de protocolo.

   Uma tupla de "(transport, protocol)" é retornada em caso de
   sucesso.

   Outros argumentos:

   * *local_addr*, if given, is a "(local_host, local_port)" tuple
     used to bind the socket to locally.  The *local_host* and
     *local_port* are looked up using "getaddrinfo()".

   * *remote_addr*, se fornecido, é uma tupla de "(remote_host,
     remote_port)" usada para conectar o soquete a um endereço remoto.
     O *remote_host* e a *remote_port* são procurados usando
     "getaddrinfo()".

   * *family*, *proto*, *flags* são os endereços familiares, protocolo
     e flags opcionais a serem passados para "getaddrinfo()" para
     resolução do *host*. Se fornecido, esses devem ser todos inteiros
     do módulo de constantes "socket" correspondente.

   * *reuse_port* avisa o kernel para permitir este endpoint para ser
     ligado a mesma porta da mesma forma que outros endpoints
     existentes estão ligados a, contanto que todos eles definam este
     flag quando forem criados. Esta opção não é suportada no Windows
     e em alguns sistemas Unix. Se a constante "SO_REUSEPORT" não
     estiver definida, então esta capacidade não é suportada.

   * *allow_broadcast* avisa o kernel para permitir que este endpoint
     envie mensagens para o endereço de broadcast.

   * *sock* pode opcionalmente ser especificado em ordem para usar um
     objeto "socket.socket" pre-existente, já conectado, para ser
     usado pelo transporte. Se especificado, *local_addr* e
     *remote_addr* devem ser omitidos (devem ser "None").

   On Windows, with "ProactorEventLoop", this method is not supported.

   Veja protocolo UDP eco cliente e protocolo UDP eco servidor para
   exemplos.

   Alterado na versão 3.4.4: Os parâmetros *family*, *proto*, *flags*,
   *reuse_address*, *reuse_port, *allow_broadcast*, e *sock* foram
   adicionados.

   Alterado na versão 3.7.6: O parâmetro *reuse_address* não é mais
   suportado devido a preocupações de segurança.

coroutine loop.create_unix_connection(protocol_factory, path=None, *, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=None)

   Cria uma conexão Unix.

   A família de soquete será "AF_UNIX"; o tipo de soquete será
   "SOCK_STREAM".

   Uma tupla de "(transport, protocol)" é retornada em caso de
   sucesso.

   *path* é o nome de um soquete de domínio Unix e é obrigatório, a
   não ser que um parâmetro *sock* seja esecificado. Soquetes Unix
   abstratos, "str", "bytes", e caminhos "Path" são suportados.

   Veja a documentação do método "loop.create_connection()" para
   informações a respeito de argumentos para este método.

   Disponibilidade: Unix.

   Novo na versão 3.7: O parâmetro *ssl_handshake_timeout*.

   Alterado na versão 3.7: O parâmetro *path* agora pode ser um
   *objeto caminho ou similar*.


Criando servidores de rede
--------------------------

coroutine loop.create_server(protocol_factory, host=None, port=None, *, family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None, ssl_handshake_timeout=None, start_serving=True)

   Cria um servidor TCP (tipo de soquete "SOCK_STREAM") escutando em
   *port* do entedeço *host*.

   Retorna um objeto "Server".

   Argumentos:

   * *protocol_factory* deve ser algo chamável, retornando uma
     implementação de protocolo.

   * O parâmetro *host* pode ser definido para diversos tipos, o qual
     determina onde o servidor deve escutar:

     * Se *host* for uma string, o servidor TCP está vinculado a
       apenas uma interface de rede, especificada por *host*.

     * Se *host* é uma sequência de strings, o servidor TCP está
       vinculado a todas as interfaces de rede especificadas pela
       sequência.

     * Se *host* é uma string vazia ou "None", todas as interfaces são
       assumidas e uma lista de múltiplos soquetes será retornada
       (muito provavelmente um para IPv4 e outro para IPv6).

   * *family* pode ser definido para "socket.AF_INET" ou "AF_INET6"
     para forçar o soquete a usar IPv4 ou IPv6. Se não for definido,
     *family* será determinado a partir do nome do servidor (por
     padrão será "AF_UNSPEC").

   * *flags* é uma máscara de bits para "getaddrinfo()".

   * *sock* pode opcionalmente ser especificado para usar um objeto
     soquete pré-existente. Se especificado, *host* e *port* não devem
     ser especificados.

   * *backlog* é o número máximo de conexões enfileiradas pasadas para
     "listen()" (padrão é 100).

   * *ssl* pode ser definido para uma instância de "SSLContext" para
     habilitar TLS sobre as conexões aceitas.

   * *reuse_address* diz ao kernel para reusar um soquete local em
     estado "TIME_WAIT", serm aguardar pela expiração natural do seu
     tempo limite. Se não especificado, será automaticamente definida
     como "True" no Unix.

   * *reuse_port* diz ao kernel para permitir que este endpoint seja
     vinculado a mesma porta que outros endpoints existentes estão
     vinculados, contanto que todos eles definam este sinalizador
     quando forem criados. Esta opção não é suportada no Windows.

   * *ssl_handshake_timeout* é (para um servidor TLS) o tempo em
     segundos para aguardar pelo aperto de mão TLS ser concluído,
     antes de abortar a conexão. "60.0" segundos se "None" (valor
     padrão).

   * Definir *start_serving* para "True" (o valor padrão) faz o
     servidor criado começar a aceitar conexões imediatamente. Quando
     definido para "False", o usuário deve aguardar com
     "Server.start_serving()" ou "Server.serve_forever()" para fazer o
     servidor começar a aceitar conexões.

   Novo na versão 3.7: Adicionado os parâmetros
   *ssl_handshake_timeout* e *start_serving*.

   Alterado na versão 3.6: A opção de soquete "TCP_NODELAY" é definida
   por padrão para todas as conexões TCP.

   Alterado na versão 3.5: Adicionado suporte para SSL/TLS na
   "ProactorEventLoop".

   Alterado na versão 3.5.1: O parâmetro *host* pode ser uma sequência
   de strings.

   Ver também:

     A função "start_server()" é uma API alternativa de alto nível que
     retorna um par de "StreamReader" e "StreamWriter" que pode ser
     usado em um código async/await.

coroutine loop.create_unix_server(protocol_factory, path=None, *, sock=None, backlog=100, ssl=None, ssl_handshake_timeout=None, start_serving=True)

   Similar a "loop.create_server()", mas trabalha com a familia de
   soquete "AF_UNIX".

   *path* é o nome de um soquete de domínio Unix, e é obrigatório, a
   não ser que um argumento *sock* seja fornecido. Soquetes Unix
   abstratos, "str", "bytes", e caminhos "Path" são suportados.

   Veja a documentação do método "loop.create_server()" para
   informações sobre argumentos para este método.

   Disponibilidade: Unix.

   Novo na versão 3.7: Os parâmetros *ssl_handshake_timeout* e
   *start_serving*.

   Alterado na versão 3.7: O parâmetro *path* agora pode ser um objeto
   "Path".

coroutine loop.connect_accepted_socket(protocol_factory, sock, *, ssl=None, ssl_handshake_timeout=None)

   Envolve uma conexão já aceita em um par transporte/protocolo.

   Este método pode ser usado por servidores que aceitam conexões fora
   do asyncio, mas que usam asyncio para manipulá-las.

   Parâmetros:

   * *protocol_factory* deve ser algo chamável, retornando uma
     implementação de protocolo.

   * *sock* é um objeto soquete pré-existente retornado a partir de
     "socket.accept".

   * *ssl* pode ser definido para um "SSLContext" para habilitar SSL
     sobre as conexões aceitas.

   * *ssl_handshake_timeout* é (para uma conexão SSL) o tempo em
     segundos para aguardar pelo aperto de mão SSL ser concluído,
     antes de abortar a conexão. "60.0" segundos se "None" (valor
     padrão).

   Retorna um par "(transport, protocol)".

   Novo na versão 3.7: O parâmetro *ssl_handshake_timeout*.

   Novo na versão 3.5.3.


Transferindo arquivos
---------------------

coroutine loop.sendfile(transport, file, offset=0, count=None, *, fallback=True)

   Envia um *file* sobre um *transport*. Retorna o número total de
   bytes enviados.

   O método usa "os.sendfile()" de alto desempenho, se disponível.

   *file* deve ser um objeto arquivo regular aberto em modo binário.

   *offset* indica a partir de onde deve iniciar a leitura do arquivo.
   Se especificado, *count* é o número total de bytes para transmitir,
   ao contrário de transmitir o arquivo até que EOF seja atingido. A
   posição do arquivo é sempre atualizada, mesmo quando este método
   levanta um erro, e "file.tell()" pode ser usado para obter o número
   atual de bytes enviados.

   *fallback* definido para "True" faz o asyncio manualmente ler e
   enviar o arquivo quando a plataforma não suporta a chamada de
   sistema sendfile (por exemplo Windows ou soquete SSL no Unix).

   Levanta "SendfileNotAvailableError" se o sistema não suporta a
   chamada de sistema *sendfile* e *fallback* é "False".

   Novo na versão 3.7.


Atualizando TLS
---------------

coroutine loop.start_tls(transport, protocol, sslcontext, *, server_side=False, server_hostname=None, ssl_handshake_timeout=None)

   Atualiza um conexão baseada em transporte existente para TLS.

   Retorna uma nova instância de transporte, que o *protocol* deve
   começar a usar imediatamente após o *await*. A instância de
   *transport* passada para o método *start_tls* nunca deve ser usada
   novamente.

   Parâmetros:

   * instâncias de *transport* e *protocol*, que métodos como
     "create_server()" e "create_connection()" retornam.

   * *sslcontext*: uma instância configurada de "SSLContext".

   * *server_side* informe "True" quando uma conexão no lado do
     servidor estiver sendo atualizada (como a que é criada por
     "create_server()").

   * *server_hostname*: define ou substitui o nome do host no qual o
     servidor alvo do certificado será comparado.

   * *ssl_handshake_timeout* é (para uma conexão TLS) o tempo em
     segundos para aguardar pelo encerramento do aperto de mão TLS,
     antes de abortar a conexão. "60.0" segundos se for``None`` (valor
     padrão).

   Novo na versão 3.7.


Observando descritores de arquivo
---------------------------------

loop.add_reader(fd, callback, *args)

   Começa a monitorar o descritor de arquivo *fd* para disponibilidade
   de leitura e invoca a *callback* com os argumentos especificados
   assim que *fd* esteja disponível para leitura.

loop.remove_reader(fd)

   Para de monitorar o descritor de arquivo *fd* para disponibilidade
   de leitura.

loop.add_writer(fd, callback, *args)

   Começa a monitorar o descritor de arquivo *fd* para disponibilidade
   de escrita e invoca a *callback* com os argumentos especificados
   assim que *fd* esteja disponível para escrita.

   Use "functools.partial()" para passar argumentos nomeados para a
   *callback*.

loop.remove_writer(fd)

   Para de monitorar o descritor de arquivo *fd* para disponibilidade
   de escrita.

Veja também a seção de Suporte a Plataformas para algumas limitações
desses métodos.


Trabalhando com objetos soquete diretamente
-------------------------------------------

Em geral, implementações de protocolo que usam APIs baseadas em
transporte, tais como "loop.create_connection()" e
"loop.create_server()" são mais rápidas que implementações que
trabalham com soquetes diretamente. Entretanto, existem alguns casos
de uso quando o desempenho não é crítica, e trabalhar com objetos
"socket" diretamente é mais conveniente.

coroutine loop.sock_recv(sock, nbytes)

   Recebe até *nbytes* do *sock*. Versão assíncrona de
   "socket.recv()".

   Retorna os dados recebidos como um objeto de bytes.

   *sock* deve ser um soquete não bloqueante.

   Alterado na versão 3.7: Apesar deste método sempre ter sido
   documentado como um método de corrotina, versões anteriores ao
   Python 3.7 retornavam um "Future". Desde o Python 3.7 este é um
   método "async def".

coroutine loop.sock_recv_into(sock, buf)

   Dados recebidos do *sock* no buffer *buf*. Modelado baseado no
   método bloqueante "socket.recv_into()".

   Retorna o número de bytes escritos no buffer.

   *sock* deve ser um soquete não bloqueante.

   Novo na versão 3.7.

coroutine loop.sock_sendall(sock, data)

   Envia *data* para o soquete *sock*. Versão assíncrona de
   "socket.sendall()".

   Este método continua a enviar para o soquete até que todos os dados
   em *data* tenham sido enviados ou um erro ocorra. "None" é
   retornado em caso de sucesso. Ao ocorrer um erro, uma exceção é
   levantada. Adicionalmente, não existe nenhuma forma de determinar
   quantos dados, se algum, foram processados com sucesso pelo
   destinatário na conexão.

   *sock* deve ser um soquete não bloqueante.

   Alterado na versão 3.7: Apesar deste método sempre ter sido
   documentado como um método de corrotina, antes do Python 3.7 ele
   retornava um "Future". A partir do Python 3.7, este é um método
   "async def".

coroutine loop.sock_connect(sock, address)

   Conecta o *sock* em um endereço *address* remoto.

   Versão assíncrona de "socket.connect()".

   *sock* deve ser um soquete não bloqueante.

   Alterado na versão 3.5.2: "address" não precisa mais ser resolvido.
   "sock_connect" irá tentar verificar se *address* já está resolvido
   chamando "socket.inet_pton()". Se não estiver, "loop.getaddrinfo()"
   será usado para resolver *address*.

   Ver também:

     "loop.create_connection()" e  "asyncio.open_connection()".

coroutine loop.sock_accept(sock)

   Aceita uma conexão. Modelado baseado no método bloqueante
   "socket.accept()".

   O soquete deve estar vinculado a um endereço e escutando por
   conexões. O valor de retorno é um par "(conn, address)" onde *conn*
   é um *novo* objeto de soquete usável para enviar e receber dados na
   conexão, e *address* é o endereço vinculado ao soquete no outro
   extremo da conexão.

   *sock* deve ser um soquete não bloqueante.

   Alterado na versão 3.7: Apesar deste método sempre ter sido
   documentado como um método de corrotina, antes do Python 3.7 ele
   retornava um "Future". Desde o Python 3.7, este é um método "async
   def".

   Ver também: "loop.create_server()" e "start_server()".

coroutine loop.sock_sendfile(sock, file, offset=0, count=None, *, fallback=True)

   Envia um arquivo usando "os.sendfile" de alto desempenho se
   possível. Retorna o número total de bytes enviados.

   Versão assíncrona de "socket.sendfile()".

   *sock* deve ser um "socket" "socket.SOCK_STREAM" não bloqueante.

   *file* deve ser um objeto arquivo regular aberto em modo binário.

   *offset* indica a partir de onde deve iniciar a leitura do arquivo.
   Se especificado, *count* é o número total de bytes para transmitir,
   ao contrário de transmitir o arquivo até que EOF seja atingido. A
   posição do arquivo é sempre atualizada, mesmo quando este método
   levanta um erro, e "file.tell()" pode ser usado para obter o número
   atual de bytes enviados.

   *fallback*, quando definido para "True", faz asyncio ler e enviar
   manualmente o arquivo, quando a plataforma não suporta a chamada de
   sistema sendfile (por exemplo Windows ou soquete SSL no Unix).

   Levanta "SendfileNotAvailableError" se o sistema não suporta
   chamadas de sistema *sendfile* e *fallback* é "False".

   *sock* deve ser um soquete não bloqueante.

   Novo na versão 3.7.


DNS
---

coroutine loop.getaddrinfo(host, port, *, family=0, type=0, proto=0, flags=0)

   Versão assíncrona de "socket.getaddrinfo()".

coroutine loop.getnameinfo(sockaddr, flags=0)

   Versão assíncrona de "socket.getnameinfo()".

Alterado na versão 3.7: Ambos os métodos *getaddrinfo* e *getnameinfo*
sempre foram documentados para retornar uma corrotina, mas antes do
Python 3.7 eles estavam, na verdade, retornando objetos
"asyncio.Future". A partir do Python 3.7, ambos os métodos são
corrotinas.


Trabalhando com encadeamentos
-----------------------------

coroutine loop.connect_read_pipe(protocol_factory, pipe)

   Registra o extremo da leitura de um *pipe* no laço de eventos.

   *protocol_factory* deve ser um chamável que retorne uma
   implementação do protocolo asyncio.

   *pipe* é um *objeto arquivo ou similar*.

   Retorna um par "(transport, protocol)", onde *transport* suporta a
   interface "ReadTransport" e *protocol* é um objeto instanciado pelo
   *protocol_factory*.

   Com o "SelectorEventLoop" do laço de eventos, o *pipe* é definido
   para modo não bloqueante.

coroutine loop.connect_write_pipe(protocol_factory, pipe)

   Registra o extremo de escrita do *pipe* no laço de eventos.

   *protocol_factory* deve ser um chamável que retorne uma
   implementação do protocolo asyncio.

   *pipe* é um *objeto arquivo ou similar*.

   Retorna um part "(transport, protocol)", onde *transport* suporta a
   interface "WriteTransport" e *protocol* é um objeto instanciado
   pelo *protocol_factory*.

   Com o "SelectorEventLoop" do laço de eventos, o *pipe* é definido
   para modo não bloqueante.

Nota:

  "SelectorEventLoop" não suporta os métodos acima no Windows. Use
  "ProactorEventLoop" ao invés para Windows.

Ver também:

  Os métodos "loop.subprocess_exec()" e "loop.subprocess_shell()".


Sinais Unix
-----------

loop.add_signal_handler(signum, callback, *args)

   Define *callback* como o tratador para o sinal *signum*.

   A função de retorno será invocada pelo *loop*, juntamente com
   outras funções de retorno enfileiradas e corrotinas executáveis
   daquele laço de eventos. Ao contrário de tratadores de sinal
   registrados usando "signal.signal()", uma função de retorno
   registrada com esta função tem autorização para interagir com o
   laço de eventos.

   Levanta "ValueError" se o número do sinal é inválido ou impossível
   de capturar. Levanta "RuntimeError" se existe um problema definindo
   o tratador.

   Use "functools.partial()" para passar argumentos nomeados para a
   *callback*.

   Assim como "signal.signal()", esta função deve ser invocada na
   thread principal.

loop.remove_signal_handler(sig)

   Remove o tratador para o sinal *sig*.

   Retorna "True" se o tratador de sinal foi removido, ou "False" se
   nenhum tratador foi definido para o sinal fornecido.

   Disponibilidade: Unix.

Ver também: O módulo "signal".


Executando código em conjuntos de threads ou processos
------------------------------------------------------

awaitable loop.run_in_executor(executor, func, *args)

   Providencia para a *func* ser chamada no executor especificado.

   O argumento *executor* deve ser uma instância
   "concurrent.futures.Executor". O executor padrão é usado se
   *executor* for "None".

   Exemplo:

      import asyncio
      import concurrent.futures

      def blocking_io():
          # File operations (such as logging) can block the
          # event loop: run them in a thread pool.
          with open('/dev/urandom', 'rb') as f:
              return f.read(100)

      def cpu_bound():
          # CPU-bound operations will block the event loop:
          # in general it is preferable to run them in a
          # process pool.
          return sum(i * i for i in range(10 ** 7))

      async def main():
          loop = asyncio.get_running_loop()

          ## Options:

          # 1. Run in the default loop's executor:
          result = await loop.run_in_executor(
              None, blocking_io)
          print('default thread pool', result)

          # 2. Run in a custom thread pool:
          with concurrent.futures.ThreadPoolExecutor() as pool:
              result = await loop.run_in_executor(
                  pool, blocking_io)
              print('custom thread pool', result)

          # 3. Run in a custom process pool:
          with concurrent.futures.ProcessPoolExecutor() as pool:
              result = await loop.run_in_executor(
                  pool, cpu_bound)
              print('custom process pool', result)

      asyncio.run(main())

   Este método retorna um objeto "asyncio.Future".

   Use "functools.partial()" para passar argumentos nomeados para
   *func*.

   Alterado na versão 3.5.3: "loop.run_in_executor()" não configura
   mais o atributo "max_workers" do executor do conjunto de thread que
   ele cria, ao invés disso ele deixa para o executor do conjunto de
   thread ("ThreadPoolExecutor") para setar o valor padrão.

loop.set_default_executor(executor)

   Define *executor* como o executor padrão usado por
   "run_in_executor()". *executor* deve ser uma instância de
   "ThreadPoolExecutor".

   Obsoleto desde a versão 3.7: Usar um executor que não é uma
   instância de "ThreadPoolExecutor" foi descontinuado, e irá disparar
   um erro no Python 3.9.

   *executor* deve ser uma instância de
   "concurrent.futures.ThreadPoolExecutor".


Tratando erros da API
---------------------

Permite customizar como exceções são tratadas no laço de eventos.

loop.set_exception_handler(handler)

   Define *handler* como o novo tratador de exceções do laço de
   eventos.

   Se *handler* for "None", o tratador de exceções padrão será
   definido. Caso contrário, *handler* deve ser um chamável com a
   assinatura combinando "(loop, context)", onde "loop" é a referência
   para o laço de eventos ativo, e "context" é um objeto "dict"
   contendo os detalhes da exceção (veja a documentação
   "call_exception_handler()" para detalhes a respeito do contexto).

loop.get_exception_handler()

   Retorna o tratador de exceção atual, ou "None" se nenhum tratador
   de exceção customizado foi definido.

   Novo na versão 3.5.2.

loop.default_exception_handler(context)

   Tratador de exceção padrão.

   Isso é chamado quando uma exceção ocorre e nenhum tratador de
   exceção foi definido. Isso pode ser chamado por um tratador de
   exceção customizado que quer passar adiante para o comportamento do
   tratador padrão.

   parâmetro *context* tem o mesmo significado que em
   "call_exception_handler()".

loop.call_exception_handler(context)

   Chama o tratador de exceção do laço de eventos atual.

   *context* é um objeto "dict" contendo as seguintes chaves (novas
   chaves podem ser introduzidas em versões futuras do Python):

   * 'message': Mensagem de erro;

   * 'exception' (opcional): Objeto Exception;

   * 'future' (opcional): instância de "asyncio.Future";

   * 'handle' (opcional): instância de "asyncio.Handle";

   * 'protocol' (opcional): instância de Protocol;

   * 'transport' (opcional): instância de Transport;

   * 'socket' (optional): "socket.socket" instance.

   Nota:

     Este método não deve ser substituído em subclasses de laços de
     evento. Para tratamento de exceções customizadas, use o método
     "set_exception_handler()".


Habilitando o modo de debug
---------------------------

loop.get_debug()

   Obtém o modo de debug ("bool") do laço de eventos.

   O valor padrão é "True" se a variável de ambiente
   "PYTHONASYNCIODEBUG" estiver definida para uma string não vazia,
   "False" caso contrário.

loop.set_debug(enabled: bool)

   Define o modo de debug do laço de eventos.

   Alterado na versão 3.7: The new "-X dev" command line option can
   now also be used to enable the debug mode.

Ver também: O modo de debug de asyncio.


Executando Subprocessos
-----------------------

Métodos descritos nestas sub-seções são de baixo nível. Em código
async/await regular, considere usar as funções convenientes de alto
nível "asyncio.create_subprocess_shell()" e
"asyncio.create_subprocess_exec()" ao invés.

Nota:

  O laço de eventos asyncio padrão no **Windows** não suporta
  subprocessos. Veja Suporte a Subprocesso no Windows para detalhes.

coroutine loop.subprocess_exec(protocol_factory, *args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)

   Cria um subprocesso a partir de um ou mais argumentos de string
   especificados por *args*.

   *args* deve ser uma lista de strings representada por:

   * "str";

   * ou "bytes", encodados na codificação do sistema de arquivos.

   A primeira string especifica o programa executável, e as strings
   remanescentes especificam os argumentos. Juntas, argumentos em
   string formam o "argv" do programa.

   Isto é similar a classe "subprocess.Popen" da biblioteca padrão ser
   chamada com "shell=False" e a lista de strings ser passada como o
   primeiro argumento; entretanto, onde "Popen" recebe apenas um
   argumento no qual é uma lista de strings, *subprocess_exec* recebe
   múltiplos argumentos string.

   O *protocol_factory* deve ser um chamável que retorne uma subclasse
   da classe "asyncio.SubprocessProtocol".

   Outros parâmetros:

   * *stdin*: either a file-like object representing a pipe to be
     connected to the subprocess's standard input stream using
     "connect_write_pipe()", or the "subprocess.PIPE"  constant
     (default). By default a new pipe will be created and connected.

   * *stdout*: either a file-like object representing the pipe to be
     connected to the subprocess's standard output stream using
     "connect_read_pipe()", or the "subprocess.PIPE" constant
     (default). By default a new pipe will be created and connected.

   * *stderr*: either a file-like object representing the pipe to be
     connected to the subprocess's standard error stream using
     "connect_read_pipe()", or one of "subprocess.PIPE" (default) or
     "subprocess.STDOUT" constants.

     By default a new pipe will be created and connected. When
     "subprocess.STDOUT" is specified, the subprocess' standard error
     stream will be connected to the same pipe as the standard output
     stream.

   * All other keyword arguments are passed to "subprocess.Popen"
     without interpretation, except for *bufsize*,
     *universal_newlines* and *shell*, which should not be specified
     at all.

   Veja o construtor da classe "subprocess.Popen" para documentação
   sobre outros argumentos.

   Retorna um par "(transport, protocol)", onde *transport* conforma
   com a classe base "asyncio.SubprocessTransport" e *protocol* é um
   objeto instanciado pelo *protocol_factory*.

coroutine loop.subprocess_shell(protocol_factory, cmd, *, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)

   Cria um subprocesso a partir do *cmd*, o qual pode ser um "str" ou
   uma string de "bytes" codificada na codificação do sistema de
   arquivos, usando a sintaxe "shell" da plataforma.

   Isto é similar a classe "subprocess.Popen" da biblioteca padrão
   sendo chanada com "shell=True".

   O argumento *protocol_factory* deve ser um chamável que retorna uma
   subclasse da classe "SubprocessProtocol".

   Veja "subprocess_exec()" para mais detalhes sobre os argumentos
   remanescentes.

   Retorna um par "(transport, protocol)", onde *transport* conforma
   com a classe base "SubprocessTransport" e *protocol* é um objeto
   instanciado pelo *protocol_factory*.

Nota:

  É responsabilidade da aplicação garantir que todos os espaços em
  branco e caracteres especiais sejam tratados apropriadamente para
  evitar vulnerabilidades de injeção shell . A função "shlex.quote()"
  pode ser usada para escapar espaços em branco e caracteres especiais
  apropriadamente em strings que serão usadas para construir comandos
  shell.


Tratadores de função de retorno
===============================

class asyncio.Handle

   Um objeto empacotador de função de retorno retornado por
   "loop.call_soon()", "loop.call_soon_threadsafe()".

   cancel()

      Cancela a função de retorno. Se a função de retorno já tiver
      sido cancelada ou executada, este método não tem efeito.

   cancelled()

      Retorna "True" se a função de retorno foi cancelada.

      Novo na versão 3.7.

class asyncio.TimerHandle

   Um objeto empacotador de função de retorno retornado por
   "loop.call_later()", e "loop.call_at()".

   Esta classe é uma subclasse de "Handle".

   when()

      Retorna o tempo de uma função de retorno agendada como "float"
      segundos.

      O tempo é um timestamp absoluto, usando a mesma referência de
      tempo que "loop.time()".

      Novo na versão 3.7.


Objetos Server
==============

Objetos Server são criados pelas funções "loop.create_server()",
"loop.create_unix_server()", "start_server()", e
"start_unix_server()".

Não instancie a classe diretamente

class asyncio.Server

   Objetos *Server* são gerenciadores de contexto assíncronos. Quando
   usados em uma instrução "async with", é garantido que o objeto
   Server está fechado e não está aceitando novas conexões quando a
   instrução "async with" estiver completa:

      srv = await loop.create_server(...)

      async with srv:
          # some code

      # At this point, srv is closed and no longer accepts new connections.

   Alterado na versão 3.7: Objeto Server é um gerenciador de contexto
   assíncrono desde o Python 3.7.

   close()

      Para de servir: fecha soquetes que estavam ouvindo e define o
      atributo "sockets" para "None".

      Os soquetes que representam conexões de clientes existentes que
      estão chegando são deixados em aberto.

      O servidor é fechado de forma assíncrona, use a corrotina
      "wait_closed()" para aguartar até que o servidor esteja fechado.

   get_loop()

      Retorna o laço de eventos associado com o objeto server.

      Novo na versão 3.7.

   coroutine start_serving()

      Começa a aceitar conexões.

      Este método é  method is idempotente, então ele pode ser
      cancelado quando o servidor já estiver servindo.

      O parâmetro somente-nomeado *start_serving* para
      "loop.create_server()" e "asyncio.start_server()" permite criar
      um objeto Server que não está aceitando conexões inicialmente.
      Neste caso "Server.start_serving()", ou "Server.serve_forever()"
      podem ser usados para fazer o Server começar a aceitar conexões.

      Novo na versão 3.7.

   coroutine serve_forever()

      Começa a aceitar conexões até que a corrotina seja cancelada.
      Cancelamento da task >>``<<serve_forever``causa o fechamento do
      servidor.

      Este método pode ser chamado se o servidor já estiver aceitando
      conexões. Apenas uma task``serve_forever`` pode existir para
      cada objeto *Server*.

      Exemplo:

         async def client_connected(reader, writer):
             # Communicate with the client with
             # reader/writer streams.  For example:
             await reader.readline()

         async def main(host, port):
             srv = await asyncio.start_server(
                 client_connected, host, port)
             await srv.serve_forever()

         asyncio.run(main('127.0.0.1', 0))

      Novo na versão 3.7.

   is_serving()

      Retorna "True" se o servidor estiver aceitando novas conexões.

      Novo na versão 3.7.

   coroutine wait_closed()

      Aguarda até o método "close()" completar.

   sockets

      List of "socket.socket" objects the server is listening on, or
      "None" if the server is closed.

      Alterado na versão 3.7: Antes do Python 3.7 "Server.sockets" era
      usado para retornar uma lista interna de soquetes do server
      diretamente. No uma cópia dessa lista é retornada.


Implementações do Laço de Eventos
=================================

asyncio vem com duas implementações de laço de eventos diferente:
"SelectorEventLoop" e "ProactorEventLoop".

By default asyncio is configured to use "SelectorEventLoop" on all
platforms.

class asyncio.SelectorEventLoop

   Um laço de eventos baseado no módulo "selectors".

   Usa o *seletor* mais eficiente disponível para a plataforma
   fornecida. Também é possível configurar manualmente a implementação
   exata do seletor a ser utilizada:

      import asyncio
      import selectors

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

   Disponibilidade: Unix, Windows.

class asyncio.ProactorEventLoop

   Um laço de eventos para Windows que usa "Conclusão de Portas I/O"
   (IOCP).

   Disponibilidade: Windows.

   An example how to use "ProactorEventLoop" on Windows:

      import asyncio
      import sys

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

   Ver também: Documentação da MSDN sobre conclusão de portas I/O.

class asyncio.AbstractEventLoop

   Classe base abstrata para laços de eventos compatíveis com asyncio.

   A seção Métodos de laço de eventos lista todos os métodos que uma
   implementação alternativa de "AbstractEventLoop" deve definir.


Exemplos
========

Perceba que todos os exemplos nesta seção **propositalmente** mostram
como usar as APIs de baixo nível do laço de eventos, tais como
"loop.run_forever()" e "loop.call_soon()". Aplicações asyncio modernas
raramente precisam ser escritas desta forma; considere usar as funções
de alto nível como "asyncio.run()".


Hello World com call_soon()
---------------------------

Um exemplo usando o método "loop.call_soon()" para agendar uma função
de retorno. A função de retorno exibe ""Hello World"" e então para o
laço de eventos:

   import asyncio

   def hello_world(loop):
       """A callback to print 'Hello World' and stop the event loop"""
       print('Hello World')
       loop.stop()

   loop = asyncio.get_event_loop()

   # Schedule a call to hello_world()
   loop.call_soon(hello_world, loop)

   # Blocking call interrupted by loop.stop()
   try:
       loop.run_forever()
   finally:
       loop.close()

Ver também:

  Um exemplo similar a Hello World criado com uma corrotina e a função
  "run()".


Exibe a data atual com call_later()
-----------------------------------

Um exemplo de uma função de retorno mostrando a data atual a cada
segundo. A função de retorno usa o método "loop.call_later()" para
reagendar a si mesma depois de 5 segundos, e então para o laço de
eventos:

   import asyncio
   import datetime

   def display_date(end_time, loop):
       print(datetime.datetime.now())
       if (loop.time() + 1.0) < end_time:
           loop.call_later(1, display_date, end_time, loop)
       else:
           loop.stop()

   loop = asyncio.get_event_loop()

   # Schedule the first call to display_date()
   end_time = loop.time() + 5.0
   loop.call_soon(display_date, end_time, loop)

   # Blocking call interrupted by loop.stop()
   try:
       loop.run_forever()
   finally:
       loop.close()

Ver também:

  Um exemplo similar a data atual criado com uma corrotina e a função
  "run()".


Observa um descritor de arquivo por eventos de leitura
------------------------------------------------------

Aguarda até que um descritor de arquivo tenha recebido alguns dados
usando o método "loop.add_reader()" e então fecha o laço de eventos:

   import asyncio
   from socket import socketpair

   # Create a pair of connected file descriptors
   rsock, wsock = socketpair()

   loop = asyncio.get_event_loop()

   def reader():
       data = rsock.recv(100)
       print("Received:", data.decode())

       # We are done: unregister the file descriptor
       loop.remove_reader(rsock)

       # Stop the event loop
       loop.stop()

   # Register the file descriptor for read event
   loop.add_reader(rsock, reader)

   # Simulate the reception of data from the network
   loop.call_soon(wsock.send, 'abc'.encode())

   try:
       # Run the event loop
       loop.run_forever()
   finally:
       # We are done. Close sockets and the event loop.
       rsock.close()
       wsock.close()
       loop.close()

Ver também:

  * Um exemplo similar usando transportes, protocolos, e o método
    "loop.create_connection()".

  * Outro exemplo similar usando a função de alto nível
    "asyncio.open_connection()" e streams.


Define tratadores de sinais para SIGINT e SIGTERM
-------------------------------------------------

(Este exemplo de "signals" apenas funciona no Unix.)

Registra tratadores para sinais "SIGINT" e "SIGTERM" usando o método
"loop.add_signal_handler()":

   import asyncio
   import functools
   import os
   import signal

   def ask_exit(signame, loop):
       print("got signal %s: exit" % signame)
       loop.stop()

   async def main():
       loop = asyncio.get_running_loop()

       for signame in {'SIGINT', 'SIGTERM'}:
           loop.add_signal_handler(
               getattr(signal, signame),
               functools.partial(ask_exit, signame, loop))

       await asyncio.sleep(3600)

   print("Event loop running for 1 hour, press Ctrl+C to interrupt.")
   print(f"pid {os.getpid()}: send SIGINT or SIGTERM to exit.")

   asyncio.run(main())
