python3 de Felizmente, o novo módulo multi-threaded e multi-processo - co-rotina co-rotina

cartilha

As versões mais recentes de todos os sistemas python3 são atualizados para python3.7, e, em seguida, atualizar o código, encontrar a mudança versão ainda é muito grande, mais ou até feito usando ETL ou operação de algumas API python2.7, não esperava que a mudança em python tão grande que parece que ele ainda está muito desatualizado. Assim, em busca de informações e saber quase no aprendizado online oficial, consulte um artigo sobre o artigo coroutine muito esclarecedor, eles devem ser mais uso desta função, multi-processo antes de usar efeito multithreading não é óbvia, mas coroutines deve ser uma arma eficiente python.

prefácio

Além de multi-processamento e multi-threaded grande criado por cima do lado de fora não é uma tarefa difícil para curar o defeito, o problema é a colaboração entre entre os processos de tratamento ou fios, porque é dependente de vários processos e programas de multi-threaded são normalmente no caso de um desbloqueado não é controlável, mas coroutines pode ser a solução perfeita para problemas de coordenação, para determinar agendamento entre coroutines pelo usuário.

Como sabemos, porque há Python GIL (Global Interpreter Lock) este material, não existe um verdadeiro multithreaded, multiprocessamento e, portanto, usará de concorrência em muitos casos, e aplicações multithread em Python também prestar atenção para áreas-chave de sincronização , menos conveniente, multi-threaded e multi-processo em vez de usar co-rotinas é uma boa escolha, porque característica atraente: a iniciativa de chamada / estado de saída, mudança de contexto evitar cpu e assim por diante ...

coroutine

conceito básico

Co-rotinas, também conhecido como co-rotina , a instrução de sintaxe aguardam por async /, é a forma recomendada para escrever aplicações assíncronas.

Ser entendido literalmente, isto é, a rotina para executar concorrentemente, é a razão entre a rosca (thread) fim mais finas de facilidade de rosca, caracterizado por permitir ao utilizador sair da chamada activa e activa, suspende a rotina atual e retorna o valor ou para executar outras tarefas, em seguida, retornar para o ponto de parada originais continuar. Espera, faz isso estranho? Nós todos sabemos que as funções lineares gerais são realizadas, é impossível dizer metade da implementação do retorno, espere um minuto e foi para o mesmo lugar para continuar. Mas alguns python familiarizado (ou outras linguagens dinâmicas) de calçados infantis todos sabemos que isso pode ser feito, a resposta é usar a declaração de rendimento. Na verdade, aqui queremos agradecer o trabalho para nós fazermos um sistema operacional (OS), porque tem getContext e swapcontext estas características, através de chamadas de sistema, podemos salvar o contexto e estado juntos, para mudar para outro contexto, essas características para alcançar a co-rotina ele fornece a base para o subjacente. Sistema operacional interrompe e mecanismo de armadilhas para alcançar este objectivo foi proporcionar uma possibilidade, por isso pode parecer com o seguinte:

>>> import asyncio

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

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

gerador apreciada (gerador)

geradores aprendidas e iteradores estudantes deve saber que há python palavra-chave yield, rendimento pode se tornar uma função de um gerador, com um retorno diferente, o estado renderia economia de valor de retorno de função na função, de modo que a próxima chamada tempo vamos continuar a executar uma função a partir do último estado, que começou a partir da próxima rendimento declaração de fazê-lo tem muitos benefícios, tais como queremos gerar um número de colunas, espaço de armazenamento, se o número de colunas é muito grande, mas nós só precisa de acesso a frente vários elementos, o rendimento é muito útil, que implementa o mecanismo de este ao circular computação, economia de espaço de armazenamento e melhorar a eficiência operacional.

correndo coroutine

  1. asyncio.run() ") Principal (" função de função é usada para executar o ponto de entrada mais alto nível

  2. Espere um co-rotina. O segmento de código seguinte imprimirá "Olá" depois de esperar por um segundo, e depois novamente à espera de impressão "mundo" após 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())
    
  3. asyncio.create_task()Função é usada para concorrentemente executar como asyncio 任务coroutine pluralidade.

    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')}")
    

Os objetos podem esperar

Se um objeto pode ser usado na demonstração esperam, então é possível esperar objetos. Muitos API asyncio são projetados para aceitar objetos podem esperar.

Os objetos podem esperar três tipos principais: co-rotina, tarefas e Futuro .

coroutine

Python coroutine pertencente pode esperar para o objecto, e, portanto, pode ser espera na outra co-rotina:

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

Neste documento, "co-rotinas" usado para representar dois conceitos intimamente relacionados:

  • função co-rotina : tal como definido sob a forma async defde uma função;
  • objetos co-rotina : telefónico coroutine função de objeto retornado.

asyncio também suporta legado gerador baseado co-rotina.

tarefa

Tarefa é usado para definir a programação para o concorrente coroutine execução.

Quando uma co-rotina por asyncio.create_task()outras funções são embalados como uma tarefa que irá automaticamente coroutine pronto para funcionar imediatamente para a programação:

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

objeto futuro

FutureÉ um especial de baixo nível pode esperar objeto representando uma operação assíncrona do resultado final .

Quando um objeto futuro é de espera , o que significa co-rotina ficarão pendentes até que o objeto seja concluída Futuro operando em outro lugar.

Em asyncio necessária para permitir o uso de retorno de chamada com base Futuro código objeto através async / await.

Em circunstâncias normais , não há necessidade de criar um código de objeto Futuro no nível de aplicação.

Futuro objetos às vezes exposto ao usuário pela biblioteca e alguns API asyncio, ele pode ser usado como uma espera objetos:

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 da função de baixo nível devolve o objecto é loop.run_in_executor().

Paralelamente a execução de tarefas

awaitable asyncio.gather (* AWS , ciclo = Nenhum , return_exceptions = FALSE )

Concomitante operação AWS sequência pode esperar para o objecto .

Se aws de um objeto pode esperar coroutine, ele é automaticamente adicionado como uma agenda de tarefas.

Se todos os objetos esperar concluída com êxito, o resultado será uma lista de todos os valores de retorno a partir da polimerização de. Ordem do valor do resultado AWS mesmo objeto pode estar à espera do fim.

Se return_exceptions é False(o padrão), causada pela primeira exceção é imediatamente propagada para espera para gather()a tarefa. aws sequência de outros objetos podem esperar não será cancelada e continuará a executar.

Se return_exceptions é True, o resultado será anormal e bem sucedido como o processamento e agregação à lista de resultados.

Se gather() cancelado , todos submetidos (ainda não concluído) podem esperar para o objeto vai ser cancelado .

Se AWS qualquer sequência ou um objeto Task Futuro é cancelado , ele será acionado como CancelledErroro mesmo processo - caso em que a gather()chamada não vai ser cancelado. Isso é para evitar Tarefa / Futuro apresentou um cancelamento faz com que outras tarefas / Futuro também foi cancelada.

import asyncio

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

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

asyncio.run(main())

# Expected output:
#
#     Task A: Compute factorial(2)...
#     Task B: Compute factorial(2)...
#     Task C: Compute factorial(2)...
#     Task A: factorial(2) = 2
#     Task B: Compute factorial(3)...
#     Task C: Compute factorial(3)...
#     Task B: factorial(3) = 6
#     Task C: Compute factorial(4)...
#     Task C: factorial(4) = 24

Exemplos de répteis

Use répteis que rastejam agrião top250

from lxml import etree
from time import time
import asyncio
import aiohttp

url = "https://movie.douban.com/top250"
header = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36",
    "content-type": "text/plain;charset=UTF-8",
}


async def fetch_content(url):
    # await asyncio.sleep(1) # 防止请求过快 等待1秒
    async with aiohttp.ClientSession(
        headers=header, connector=aiohttp.TCPConnector(ssl=False)
    ) as session:
        async with session.get(url) as response:
            return await response.text()


async def parse(url):
    page = await fetch_content(url)
    html = etree.HTML(page)

    xpath_movie = '//*[@id="content"]/div/div[1]/ol/li'
    xpath_title = './/span[@class="title"]'
    xpath_pages = '//*[@id="content"]/div/div[1]/div[2]/a'
    xpath_descs = './/span[@class="inq"]'
    xpath_links = './/div[@class="info"]/div[@class="hd"]/a'

    pages = html.xpath(xpath_pages)  # 所有页面的链接都在底部获取
    fetch_list = []
    result = []

    for element_movie in html.xpath(xpath_movie):
        result.append(element_movie)

    for p in pages:
        fetch_list.append(url + p.get("href"))  # 解析翻页按钮对应的链接 组成完整后边页面链接

    tasks = [fetch_content(url) for url in fetch_list]  # 并行处理所有翻页的页面
    pages = await asyncio.gather(*tasks)
    # 并发 运行 aws 序列中的 可等待对象。
    # 如果 aws 中的某个可等待对象为协程,它将自动作为一个任务加入日程。
    # 如果所有可等待对象都成功完成,结果将是一个由所有返回值聚合而成的列表。结果值的顺序与 aws 中可等待对象的顺序一致。
    for page in pages:
        html = etree.HTML(page)
        for element_movie in html.xpath(xpath_movie):
            result.append(element_movie)

    for i, movie in enumerate(result, 1):
        title = movie.find(xpath_title).text
        desc = (
            "<" + movie.find(xpath_descs).text + ">"
            if movie.find(xpath_descs) is not None
            else None
        )
        link = movie.find(xpath_links).get("href")
        print(i, title, desc, link)


async def main():
    start = time()
    for i in range(5):
        await parse(url)
    end = time()
    print("Cost {} seconds".format((end - start) / 5))


if __name__ == "__main__":
    asyncio.run(main())

artigo de referência

  1. De 0 a 1, Python Evolução do caminho de programação assíncrona
  2. Python3 Async / explicação Await
  3. documentos oficiais e co-rotina tarefa
Publicado 34 artigos originais · ganhou elogios 13 · vê 50000 +

Acho que você gosta

Origin blog.csdn.net/frone/article/details/89231000
Recomendado
Clasificación