Diretório do artigo
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
-
asyncio.run()
") Principal (" função de função é usada para executar o ponto de entrada mais alto nível -
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())
-
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 def
de 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 CancelledError
o 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())