Corrotinas e Tarefas
********************

Esta seção descreve APIs assíncronas de alto nível para trabalhar com
corrotinas e tarefas.

* Corrotinas

* Aguardáveis

* Executando um programa asyncio

* Criando Tarefas

* Dormindo

* Executando tarefas concorrentemente

* Protegendo contra cancelamento

* Tempo limite

* Primitivas de Espera

* Executando em Threads

* Agendando a partir de outras Threads

* Introspecção

* Objeto Task

* Corrotinas baseadas em gerador


Corrotinas
==========

*Corrotinas* declaradas com a sintaxe async/await é a forma preferida
de escrever aplicações assíncronas. Por exemplo, o seguinte trecho de
código imprime "hello", espera 1 segundo, e então imprime "world":

   >>> import asyncio

   >>> async def main():
   ...     print('hello')
   ...     await asyncio.sleep(1)
   ...     print('world')

   >>> asyncio.run(main())
   hello
   world

Perceba que simplesmente chamar uma corrotina não irá agendá-la para
ser executada:

   >>> main()
   <coroutine object main at 0x1053bb7c8>

Para realmente executar uma corrotina, asyncio fornece três mecanismos
principais:

* A função "asyncio.run()" para executar a função "main()" do ponto de
  entrada no nível mais alto (veja o exemplo acima.)

* Aguardando uma corrotina. O seguinte trecho de código exibirá
  "hello" após esperar por 1 segundo e, em seguida, exibirá "world"
  após esperar por *outros* 2 segundos:

     import asyncio
     import time

     async def say_after(delay, what):
         await asyncio.sleep(delay)
         print(what)

     async def main():
         print(f"started at {time.strftime('%X')}")

         await say_after(1, 'hello')
         await say_after(2, 'world')

         print(f"finished at {time.strftime('%X')}")

     asyncio.run(main())

  Resultado esperado:

     started at 17:13:52
     hello
     world
     finished at 17:13:55

* A função "asyncio.create_task()" para executar corrotinas
  concorrentemente como "Tasks" asyncio.

  Vamos modificar o exemplo acima e executar duas corrotinas
  "say_after" *concorrentemente*:

     async def main():
         task1 = asyncio.create_task(
             say_after(1, 'hello'))

         task2 = asyncio.create_task(
             say_after(2, 'world'))

         print(f"started at {time.strftime('%X')}")

         # Wait until both tasks are completed (should take
         # around 2 seconds.)
         await task1
         await task2

         print(f"finished at {time.strftime('%X')}")

  Perceba que a saída esperada agora mostra que o trecho de código é
  executado 1 segundo mais rápido do que antes:

     started at 17:14:32
     hello
     world
     finished at 17:14:34


Aguardáveis
===========

Dizemos que um objeto é um objeto **aguardável** se ele pode ser usado
em uma expressão "await". Muitas APIs asyncio são projetadas para
aceitar aguardáveis.

Existem três tipos principais de objetos *aguardáveis*:
**corrotinas**, **Tarefas**, e **Futuros**.

-[ Corrotinas ]-

Corrotinas Python são *aguardáveis* e portanto podem ser aguardadas a
partir de outras corrotinas:

   import asyncio

   async def nested():
       return 42

   async def main():
       # Nothing happens if we just call "nested()".
       # A coroutine object is created but not awaited,
       # so it *won't run at all*.
       nested()

       # Let's do it differently now and await it:
       print(await nested())  # will print "42".

   asyncio.run(main())

Importante:

  Nesta documentação, o termo "corrotina" pode ser usado para dois
  conceitos intimamente relacionados:

  * uma *função de corrotina*: uma função "async def";

  * um *objeto de corrotina*: um objeto retornado ao chamar uma
    *função de corrotina*.

asyncio também suporta corrotinas legadas baseadas em geradores.

-[ Tarefas ]-

*Tarefas* são usadas para agendar corrotinas *concorrentemente*.

Quando uma corrotina é envolta em uma *tarefa* com funções como
"asyncio.create_task()", a corrotina é automaticamente agendada para
executar em breve:

   import asyncio

   async def nested():
       return 42

   async def main():
       # Schedule nested() to run soon concurrently
       # with "main()".
       task = asyncio.create_task(nested())

       # "task" can now be used to cancel "nested()", or
       # can simply be awaited to wait until it is complete:
       await task

   asyncio.run(main())

-[ Futuros ]-

Um "Future" é um objeto aguardável especial de **baixo nível** que
representa um **resultado eventual** de uma operação assíncrona.

Quando um objeto Future é *aguardado* isso significa que a corrotina
irá esperar até que o Future seja resolvido em algum outro local.

Objetos Future em asyncio são necessários para permitir que código
baseado em função de retorno seja utilizado com async/await.

Normalmente **não existe necessidade** em criar objetos Future no
nível de código da aplicação.

Objetos Future, algumas vezes expostos por bibliotecas e algumas APIs
asyncio, podem ser aguardados:

   async def main():
       await function_that_returns_a_future_object()

       # this is also valid:
       await asyncio.gather(
           function_that_returns_a_future_object(),
           some_python_coroutine()
       )

Um bom exemplo de uma função de baixo nível que retorna um objeto
Future é "loop.run_in_executor()".


Executando um programa asyncio
==============================

asyncio.run(coro, *, debug=False)

   Executa a *corrotina* *coro* e retorna o resultado.

   Esta função executa a corrotina passada, tomando cuidado de
   gerenciar o laço de eventos asyncio, *finalizando geradores
   assíncronos*, e encerrando a threadpool.

   Esta função não pode ser chamada quando outro laço de eventos
   asyncio está executando na mesma thread.

   Se *debug* for "True", o laço de eventos irá ser executado em modo
   debug.

   Esta função sempre cria um novo laço de eventos e fecha-o no final.
   Ela deve ser usada como um ponto de entrada principal para
   programas asyncio, e deve idealmente ser chamada apenas uma vez.

   Exemplo:

      async def main():
          await asyncio.sleep(1)
          print('hello')

      asyncio.run(main())

   Novo na versão 3.7.

   Alterado na versão 3.9: Atualizado para usar
   "loop.shutdown_default_executor()".

   Nota:

     O código-fonte para "asyncio.run()" pode ser encontrado em
     Lib/asyncio/runners.py.


Criando Tarefas
===============

asyncio.create_task(coro, *, name=None)

   Envolva a corrotina *coro* em uma "Task" e agende sua execução.
   Retorne o objeto Task.

   Se *name* não for "None", ele é setado como o nome da tarefa usando
   "Task.set_name()".

   A tarefa é executada no laço e retornada por "get_running_loop()",
   "RuntimeError" é levantado se não existir nenhum loop na thread
   atual.

   Importante:

     Save a reference to the result of this function, to avoid a task
     disappearing mid execution.

   Novo na versão 3.7.

   Alterado na versão 3.8: Adicionado o parâmetro "name".


Dormindo
========

coroutine asyncio.sleep(delay, result=None, *, loop=None)

   Bloqueia por *delay* segundos.

   Se *result* é fornecido, é retornado para o autor da chamada quando
   a corrotina termina.

   "sleep()" sempre suspende a tarefa atual, permitindo que outras
   tarefas sejam executadas.

   Configurando o delay para 0 fornece um caminho otimizado para
   permitir que outras tarefas executem. Isto pode ser usado por
   funções de longa execução para evitar que bloqueiem o laço de
   eventos por toda a duração da chamada da função.

   Deprecated since version 3.8, will be removed in version 3.10: O
   parâmetro *loop*.

   Exemplo de uma corrotina exibindo a data atual a cada segundo
   durante 5 segundos:

      import asyncio
      import datetime

      async def display_date():
          loop = asyncio.get_running_loop()
          end_time = loop.time() + 5.0
          while True:
              print(datetime.datetime.now())
              if (loop.time() + 1.0) >= end_time:
                  break
              await asyncio.sleep(1)

      asyncio.run(display_date())


Executando tarefas concorrentemente
===================================

awaitable asyncio.gather(*aws, loop=None, return_exceptions=False)

   Executa objetos aguardáveis na sequência *aws* de forma
   *concorrente*.

   Se qualquer aguardável em *aws* é uma corrotina, ele é
   automaticamente agendado como uma Tarefa.

   Se todos os aguardáveis forem concluídos com sucesso, o resultado é
   uma lista agregada de valores retornados. A ordem dos valores
   resultantes corresponde a ordem dos aguardáveis em *aws*.

   Se *return_exceptions* for "False" (valor padrão), a primeira
   exceção levantada é imediatamente propagada para a tarefa que
   espera em "gather()". Outros aguardáveis na sequência *aws* **não
   serão cancelados** e irão continuar a executar.

   Se *return_exceptions* for "True", exceções são tratadas da mesma
   forma que resultados com sucesso, e agregadas na lista de
   resultados.

   Se "gather()" for *cancelado*, todos os aguardáveis que foram
   submetidos (que não foram concluídos ainda) também são
   *cancelados*.

   Se qualquer Tarefa ou Futuro da sequência *aws* for *cancelado*,
   ele é tratado como se tivesse levantado "CancelledError" -- a
   chamada para "gather()" **não** é cancelada neste caso. Isso existe
   para prevenir que o cancelamento de uma Tarefa/Futuro submetida
   ocasione outras Tarefas/Futuros a serem cancelados.

   Deprecated since version 3.8, will be removed in version 3.10: O
   parâmetro *loop*.

   Exemplo:

      import asyncio

      async def factorial(name, number):
          f = 1
          for i in range(2, number + 1):
              print(f"Task {name}: Compute factorial({number}), currently i={i}...")
              await asyncio.sleep(1)
              f *= i
          print(f"Task {name}: factorial({number}) = {f}")
          return f

      async def main():
          # Schedule three calls *concurrently*:
          L = await asyncio.gather(
              factorial("A", 2),
              factorial("B", 3),
              factorial("C", 4),
          )
          print(L)

      asyncio.run(main())

      # Expected output:
      #
      #     Task A: Compute factorial(2), currently i=2...
      #     Task B: Compute factorial(3), currently i=2...
      #     Task C: Compute factorial(4), currently i=2...
      #     Task A: factorial(2) = 2
      #     Task B: Compute factorial(3), currently i=3...
      #     Task C: Compute factorial(4), currently i=3...
      #     Task B: factorial(3) = 6
      #     Task C: Compute factorial(4), currently i=4...
      #     Task C: factorial(4) = 24
      #     [2, 6, 24]

   Nota:

     Se *return_exceptions* for False, cancelar gather() depois que
     ele foi marcado como concluído não irá cancelar quaisquer
     aguardáveis submetidos. Por exemplo, gather pode ser marcado como
     concluído após propagar uma exceção para o autor da chamada,
     portanto, chamar "gather.cancel()" após capturar uma exceção
     (levantada por um dos aguardáveis) a partir de gather não irá
     cancelar quaisquer outros aguardáveis.

   Alterado na versão 3.7: Se *gather* por si mesmo for cancelado, o
   cancelamento é propagado independente de *return_exceptions*.


Protegendo contra cancelamento
==============================

awaitable asyncio.shield(aw, *, loop=None)

   Protege um objeto aguardável de ser "cancelado".

   Se *aw* é uma corrotina, ela é automaticamente agendada como uma
   Tarefa.

   A instrução:

      res = await shield(something())

   é equivalente a:

      res = await something()

   *exceto* que se a corrotina contendo-a for cancelada, a Tarefa
   executando em "something()" não é cancelada. Do ponto de vista de
   "something()", o cancelamento não aconteceu. Apesar do autor da
   chamada ainda estar cancelado, então a expressão "await" ainda
   levanta um "CancelledError".

   Se "something()" é cancelada por outros meios (isto é, dentro ou a
   partir de si mesma) isso também iria cancelar "shield()".

   Se for desejado ignorar completamente os cancelamentos (não
   recomendado) a função "shield()" deve ser combinada com uma
   cláusula try/except, conforme abaixo:

      try:
          res = await shield(something())
      except CancelledError:
          res = None

   Deprecated since version 3.8, will be removed in version 3.10: O
   parâmetro *loop*.


Tempo limite
============

coroutine asyncio.wait_for(aw, timeout, *, loop=None)

   Espera o aguardável *aw* concluir sem ultrapassar o tempo limite
   "timeout".

   Se *aw* é uma corrotina, ela é automaticamente agendada como uma
   Tarefa.

   *timeout* pode ser "None", ou um ponto flutuante, ou um número
   inteiro de segundos para aguardar. Se *timeout* é "None", aguarda
   até o future encerrar.

   Se o tempo limite timeout for atingido, ele cancela a tarefa e
   levanta "asyncio.TimeoutError".

   Para evitar o "cancelamento" da tarefa, envolva-a com "shield()".

   A função irá aguardar até o future ser realmente cancelado, então o
   tempo total de espera pode exceder o tempo limite *timeout*. Se uma
   exceção ocorrer durante o cancelamento, ela será propagada.

   Se ele for cancelado, o future *aw* também é cancelado.

   Deprecated since version 3.8, will be removed in version 3.10: O
   parâmetro *loop*.

   Exemplo:

      async def eternity():
          # Sleep for one hour
          await asyncio.sleep(3600)
          print('yay!')

      async def main():
          # Wait for at most 1 second
          try:
              await asyncio.wait_for(eternity(), timeout=1.0)
          except asyncio.TimeoutError:
              print('timeout!')

      asyncio.run(main())

      # Expected output:
      #
      #     timeout!

   Alterado na versão 3.7: Quando *aw* é cancelado devido a um tempo
   limite, "wait_for" aguarda que *aw* seja cancelado. Anteriormente,
   ele levantava "asyncio.TimeoutError" imediatamente.


Primitivas de Espera
====================

coroutine asyncio.wait(aws, *, loop=None, timeout=None, return_when=ALL_COMPLETED)

   Executa objetos aguardáveis no iterável *aws* concorrentemente e
   bloqueia até que a condição especificada por *return_when* seja
   atingida.

   O iterável *aws* não deve ser vazio.

   Retorna dois conjuntos de Tarefas/Futuros: "(done, pending)".

   Uso:

      done, pending = await asyncio.wait(aws)

   *timeout* (um ponto flutuante ou inteiro), se especificado, pode
   ser usado para controlar o número máximo de segundos para aguardar
   antes de retornar.

   Perceba que esta função não levanta "asyncio.TimeoutError". Futuros
   ou Tarefas que não estão concluídas quando o tempo limite é
   excedido são simplesmente retornadas no segundo conjunto.

   *return_when* indica quando esta função deve retornar. Ele deve ser
   uma das seguintes constantes:

   +-------------------------------+------------------------------------------+
   | Constante                     | Descrição                                |
   |===============================|==========================================|
   | "FIRST_COMPLETED"             | A função irá retornar quando qualquer    |
   |                               | futuro terminar ou for cancelado.        |
   +-------------------------------+------------------------------------------+
   | "FIRST_EXCEPTION"             | A função irá retornar quando qualquer    |
   |                               | futuro encerrar levantando uma exceção.  |
   |                               | Se nenhum futuro levantar uma exceção,   |
   |                               | então é equivalente a "ALL_COMPLETED".   |
   +-------------------------------+------------------------------------------+
   | "ALL_COMPLETED"               | A função irá retornar quando todos os    |
   |                               | futuros encerrarem ou forem cancelados.  |
   +-------------------------------+------------------------------------------+

   Diferente de "wait_for()", "wait()" não cancela os futuros quando
   um tempo limite é atingido.

   Obsoleto desde a versão 3.8: Se qualquer aguardável em *aws* for
   uma corrotina, ela é automaticamente agendada como uma tarefa.
   Passar objetos que são corrotinas para "wait()" diretamente está
   descontinuado, pois leva a comportamentos confusos.

   Deprecated since version 3.8, will be removed in version 3.10: O
   parâmetro *loop*.

   Nota:

     "wait()" agenda corrotinas como Tarefas automaticamente e
     posteriormente retorna esses objetos Tarefas criados
     implicitamente em conjuntos "(done, pending)". Portanto o
     seguinte código não irá funcionar como esperado:

        async def foo():
            return 42

        coro = foo()
        done, pending = await asyncio.wait({coro})

        if coro in done:
            # This branch will never be run!

     Aqui está a forma como o trecho de código acima pode ser
     consertado:

        async def foo():
            return 42

        task = asyncio.create_task(foo())
        done, pending = await asyncio.wait({task})

        if task in done:
            # Everything will work as expected now.

   Deprecated since version 3.8, will be removed in version 3.11:
   Passar objetos corrotina para "wait()" diretamente foi
   descontinuado.

asyncio.as_completed(aws, *, loop=None, timeout=None)

   Executa objetos aguardáveis no iterável *aws* concorrentemente.
   Retorna um iterador de corrotinas. Cada corrotina retornada pode
   ser aguardada para obter o primeiro resultado seguinte a partir do
   iterável dos aguardáveis restantes.

   Levanta "asyncio.TimeoutError" se o tempo limite ocorrer antes que
   todos os futuros tenham encerrado.

   Deprecated since version 3.8, will be removed in version 3.10: O
   parâmetro *loop*.

   Exemplo:

      for coro in as_completed(aws):
          earliest_result = await coro
          # ...


Executando em Threads
=====================

coroutine asyncio.to_thread(func, /, *args, **kwargs)

   Executa a função *func* assincronamente em uma thread separada.

   Quaisquer *args e **kwargs fornecidos para esta função são
   diretamente passados para *func*. Além disso, o
   "contextvars.Context" atual é propagado, permitindo que variáveis
   de contexto da thread do laço de eventos sejam acessadas na thread
   separada.

   Retorna uma corrotina que pode ser aguardada para obter o resultado
   eventual de *func*.

   Esta função de corrotina é pretendida primariamente para ser usada
   para execução de funções/métodos vinculados a IO, que poderiam de
   outra forma bloquear o laço de eventos se eles fossem executados na
   thread principal. Por exemplo:

      def blocking_io():
          print(f"start blocking_io at {time.strftime('%X')}")
          # Note that time.sleep() can be replaced with any blocking
          # IO-bound operation, such as file operations.
          time.sleep(1)
          print(f"blocking_io complete at {time.strftime('%X')}")

      async def main():
          print(f"started main at {time.strftime('%X')}")

          await asyncio.gather(
              asyncio.to_thread(blocking_io),
              asyncio.sleep(1))

          print(f"finished main at {time.strftime('%X')}")


      asyncio.run(main())

      # Expected output:
      #
      # started main at 19:50:53
      # start blocking_io at 19:50:53
      # blocking_io complete at 19:50:54
      # finished main at 19:50:54

   Chamar diretamente *blocking_io()* em qualquer corrotina iria
   bloquear o laço de eventos durante a sua duração, resultando em 1
   segundo adicional no tempo de execução. Ao invés disso, ao utilizar
   *asyncio.to_thread()*, nós podemos executá-la em uma thread
   separada sem bloquear o laço de eventos.

   Nota:

     Devido ao *GIL*, *asyncio.to_thread()* pode tipicamente ser usado
     apenas para fazer funções vinculadas a IO não-bloqueantes.
     Entretanto, para módulos de extensão que liberam o GIL ou
     implementações alternativas do Python que não tem um,
     *asyncio.to_thread()* também pode ser usado para funções
     vinculadas a CPU.

   Novo na versão 3.9.


Agendando a partir de outras Threads
====================================

asyncio.run_coroutine_threadsafe(coro, loop)

   Envia uma corrotina para o laço de eventos fornecido. Seguro para
   thread.

   Retorna um "concurrent.futures.Future" para aguardar pelo resultado
   de outra thread do sistema operacional.

   Esta função destina-se a ser chamada partir de uma thread diferente
   do sistema operacional, da qual o laço de eventos está executando.
   Exemplo:

      # Create a coroutine
      coro = asyncio.sleep(1, result=3)

      # Submit the coroutine to a given loop
      future = asyncio.run_coroutine_threadsafe(coro, loop)

      # Wait for the result with an optional timeout argument
      assert future.result(timeout) == 3

   Se uma exceção for levantada na corrotina, o Futuro retornado será
   notificado. Isso também pode ser usado para cancelar a tarefa no
   laço de eventos:

      try:
          result = future.result(timeout)
      except asyncio.TimeoutError:
          print('The coroutine took too long, cancelling the task...')
          future.cancel()
      except Exception as exc:
          print(f'The coroutine raised an exception: {exc!r}')
      else:
          print(f'The coroutine returned: {result!r}')

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

   Ao contrário de outras funções asyncio, esta função requer que o
   argumento *loop* seja passado explicitamente.

   Novo na versão 3.5.1.


Introspecção
============

asyncio.current_task(loop=None)

   Retorna a instância "Task" atualmente em execução, ou "None" se
   nenhuma tarefa estiver executando.

   Se *loop* for "None", então "get_running_loop()" é usado para obter
   o laço atual.

   Novo na versão 3.7.

asyncio.all_tasks(loop=None)

   Retorna um conjunto de objetos "Task" ainda não concluídos a serem
   executados pelo laço.

   Se *loop* for "None", então "get_running_loop()" é usado para obter
   o laço atual.

   Novo na versão 3.7.


Objeto Task
===========

class asyncio.Task(coro, *, loop=None, name=None)

   Um objeto "similar a Futuro" que executa uma corrotina Python. Não
   é seguro para thread.

   Tarefas são usadas para executar corrotinas em laços de eventos. Se
   uma corrotina espera por um Futuro, a Tarefa suspende a execução da
   corrotina e aguarda a conclusão do Futuro. Quando o Futuro é
   *concluído*, a execução da corrotina contida é retomada.

   Laço de eventos usam agendamento cooperativo: um ciclo de evento
   executa uma Tarefa de cada vez. Enquanto uma Tarefa aguarda a
   conclusão de um Futuro, o laço de eventos executa outras Tarefas,
   funções de retorno, ou executa operações de IO.

   Use a função de alto nível "asyncio.create_task()" para criar
   Tarefas, ou as funções de baixo nível "loop.create_task()" ou
   "ensure_future()". Instanciação manual de Tarefas é desencorajado.

   Para cancelar uma Tarefa em execução, use o método "cancel()".
   Chamar ele fará com que a Tarefa levante uma exceção
   "CancelledError" dentro da corrotina contida. Se a corrotina
   estiver esperando por um objeto Future durante o cancelamento, o
   objeto Future será cancelado.

   "cancelled()" pode ser usado para verificar se a Tarefa foi
   cancelada. O método retorna "True" se a corrotina envolta não
   suprimiu a exceção "CancelledError" e foi na verdade cancelada.

   "asyncio.Task" herda de "Future" todas as suas APIs exceto
   "Future.set_result()" e "Future.set_exception()".

   Tarefas suportam o módulo "contextvars". Quando a Tarefa é criada,
   ela copia o contexto atual e posteriormente executa sua corrotina
   no contexto copiado.

   Alterado na versão 3.7: Adicionado suporte para o módulo
   "contextvars".

   Alterado na versão 3.8: Adicionado o parâmetro "name".

   Deprecated since version 3.8, will be removed in version 3.10: O
   parâmetro *loop*.

   cancel(msg=None)

      Solicita o cancelamento da Tarefa.

      Isto prepara para uma exceção "CancelledError" ser lançada na
      corrotina contida no próximo ciclo do laço de eventos.

      A corrotina então tem uma chance de limpar ou até mesmo negar a
      requisição, suprimindo a exceção com um bloco "try" ... ...
      "except CancelledError" ... "finally". Portanto, ao contrário de
      "Future.cancel()", "Task.cancel()" não garante que a Tarefa será
      cancelada, apesar que suprimir o cancelamento completamente não
      é comum, e é ativamente desencorajado.

      Alterado na versão 3.9: Adicionado o parâmetro "msg".

      O seguinte exemplo ilustra como corrotinas podem interceptar o
      cancelamento de requisições:

         async def cancel_me():
             print('cancel_me(): before sleep')

             try:
                 # Wait for 1 hour
                 await asyncio.sleep(3600)
             except asyncio.CancelledError:
                 print('cancel_me(): cancel sleep')
                 raise
             finally:
                 print('cancel_me(): after sleep')

         async def main():
             # Create a "cancel_me" Task
             task = asyncio.create_task(cancel_me())

             # Wait for 1 second
             await asyncio.sleep(1)

             task.cancel()
             try:
                 await task
             except asyncio.CancelledError:
                 print("main(): cancel_me is cancelled now")

         asyncio.run(main())

         # Expected output:
         #
         #     cancel_me(): before sleep
         #     cancel_me(): cancel sleep
         #     cancel_me(): after sleep
         #     main(): cancel_me is cancelled now

   cancelled()

      Retorna "True" se a Tarefa for *cancelada*.

      A Tarefa é *cancelada* quando o cancelamento foi requisitado com
      "cancel()" e a corrotina contida propagou a exceção
      "CancelledError" gerada nela.

   done()

      Retorna "True" se a Tarefa estiver *concluída*.

      Uma Tarefa está *concluída* quando a corrotina contida retornou
      um valor, ou levantou uma exceção, ou a Tarefa foi cancelada.

   result()

      Retorna o resultado da Tarefa.

      Se a Tarefa estiver *concluída*, o resultado da corrotina
      contida é retornado (ou se a corrotina levantou uma exceção,
      essa exceção é re-levantada.)

      Se a Tarefa foi *cancelada*, este método levanta uma exceção
      "CancelledError".

      Se o resultado da Tarefa não estiver disponível ainda, este
      método levanta uma exceção "InvalidStateError".

   exception()

      Retorna a exceção de uma Tarefa.

      Se a corrotina contida levantou uma exceção, essa exceção é
      retornada. Se a corrotina contida retornou normalmente, este
      método retorna "None".

      Se a Tarefa foi *cancelada*, este método levanta uma exceção
      "CancelledError".

      Se a Tarefa não estiver *concluída* ainda, este método levanta
      uma exceção "InvalidStateError".

   add_done_callback(callback, *, context=None)

      Adiciona uma função de retorno para ser executada quando a
      Tarefa estiver *concluída*.

      Este método deve ser usado apenas em código de baixo nível
      baseado em funções de retorno.

      Veja a documentação para "Future.add_done_callback()" para mais
      detalhes.

   remove_done_callback(callback)

      Remove *callback* da lista de funções de retorno.

      Este método deve ser usado apenas em código de baixo nível
      baseado em funções de retorno.

      Veja a documentação do método "Future.remove_done_callback()"
      para mais detalhes.

   get_stack(*, limit=None)

      Retorna a lista de frames da pilha para esta Tarefa.

      Se a corrotina contida não estiver concluída, isto retorna a
      pilha onde ela foi suspensa. Se a corrotina foi concluída com
      sucesso ou foi cancelada, isto retorna uma lista vazia. Se a
      corrotina foi terminada por uma exceção, isto retorna a lista de
      frames do traceback (situação da pilha de execução).

      Os quadros são sempre ordenados dos mais antigos para os mais
      recentes.

      Apenas um frame da pilha é retornado para uma corrotina
      suspensa.

      O argumento opcional *limit* define o o número de frames máximo
      para retornar; por padrão todos os frames disponíveis são
      retornados. O ordenamento da lista retornada é diferente
      dependendo se uma pilha ou um traceback (situação da pilha de
      execução) é retornado: os frames mais recentes de uma pilha são
      retornados, mas os frames mais antigos de um traceback são
      retornados. (Isso combina com o comportamento do módulo
      traceback.)

   print_stack(*, limit=None, file=None)

      Exibe a pilha ou situação da pilha de execução para esta Tarefa.

      Isto produz uma saída similar a do módulo traceback para frames
      recuperados por "get_stack()".

      O argumento *limit* é passado para "get_stack()" diretamente.

      O argumento *file* é um fluxo de entrada e saída para o qual a
      saída é escrita; por padrão a saída é escrita para "sys.stderr".

   get_coro()

      Retorna o objeto corrotina contido pela "Task".

      Novo na versão 3.8.

   get_name()

      Retorna o nome da Tarefa.

      Se nenhum nome foi explicitamente designado para a Tarefa, a
      implementação padrão asyncio da classe Task gera um nome padrão
      durante a instanciação.

      Novo na versão 3.8.

   set_name(value)

      Define o nome da Tarefa.

      O argumento *value* pode ser qualquer objeto, o qual é então
      convertido para uma string.

      Na implementação padrão da Tarefa, o nome será visível na
      "repr()" de saída de um objeto task.

      Novo na versão 3.8.


Corrotinas baseadas em gerador
==============================

Nota:

  Suporte para corrotinas baseadas em gerador está **descontinuado** e
  será removido em Python 3.11.

Corrotinas baseadas em gerador antecedem a sintaxe async/await. Elas
são geradores Python que usam expressões "yield from" para aguardar
Futuros e outras corrotinas.

Corrotinas baseadas em gerador devem ser decoradas com
"@asyncio.coroutine", apesar disso não ser forçado.

@asyncio.coroutine

   Decorador para marcar corrotinas baseadas em gerador.

   Este decorador permite que corrotinas legadas baseadas em gerador
   sejam compatíveis com código async/await:

      @asyncio.coroutine
      def old_style_coroutine():
          yield from asyncio.sleep(1)

      async def main():
          await old_style_coroutine()

   Este decorador não deve ser usado para corrotinas "async def".

   Deprecated since version 3.8, will be removed in version 3.11: Use
   "async def" ao invés.

asyncio.iscoroutine(obj)

   Retorna "True" se *obj* é um objeto corrotina.

   Este método é diferente de "inspect.iscoroutine()" porque ele
   retorna "True" para corrotinas baseadas em gerador.

asyncio.iscoroutinefunction(func)

   Retorna "True" se *func* é uma função de corrotina.

   Este método é diferente de "inspect.iscoroutinefunction()" porque
   ele retorna "True" para funções de corrotina baseadas em gerador,
   decoradas com "@coroutine".
