Я пытаюсь создать простой поисковый робот, используя trio
и asks
. Я использую питомник для одновременного запуска нескольких сканеров и канал памяти для ведения списка URL-адресов для посещения.
Каждый поисковый робот получает клоны обоих концов этого канала, поэтому они могут получить URL-адрес (через Receive_channel), прочитать его, найти и добавить новые URL-адреса для посещения (через send_channel).
async def main():
send_channel, receive_channel = trio.open_memory_channel(math.inf)
async with trio.open_nursery() as nursery:
async with send_channel, receive_channel:
nursery.start_soon(crawler, send_channel.clone(), receive_channel.clone())
nursery.start_soon(crawler, send_channel.clone(), receive_channel.clone())
nursery.start_soon(crawler, send_channel.clone(), receive_channel.clone())
async def crawler(send_channel, receive_channel):
async for url in receive_channel: # I'm a consumer!
content = await ...
urls_found = ...
for u in urls_found:
await send_channel.send(u) # I'm a producer too!
В этом сценарии потребители являются производителями. Как изящно все остановить?
Условия отключения всего:
- канал пуст
- И
- все поисковые роботы застревают в первом цикле for, ожидая появления URL-адреса в Receive_channel (что... больше не произойдет)
Я пробовал с async with send_channel
внутри crawler()
, но не смог найти хороший способ сделать это. Я также пытался найти какой-то другой подход (какой-то рабочий пул, привязанный к каналу памяти и т. д.), но и здесь не повезло.