簡體   English   中英

Asyncio任務,將自身的副本添加到循環中

[英]Asyncio task that adds copies of itself to the loop

我對asyncio還是很陌生,目前無法自己解決這個問題,將不勝感激。

用例如下:

  • 當有太多請求發送到該服務時,我需要從該限制和黑名單中獲取數據。
  • 我需要向該Web服務發出大量數據請求
  • Web服務以分頁的方式發送數據,即,當給定請求的數據太多時,需要進行后續請求以獲取更多頁面。
  • 通過檢查來自特定請求的響應,可以確定是否需要提取更多頁面。
  • 一旦在客戶端接收到數據,就需要將其寫入磁盤

因此,在我看來,設置可能如下:-准備了需要發出的請求的初始列表-信號量控制每單位時間發出多少請求以控制節流。 -所有初始請求都添加到循環中。 -收到響應后,將分派一個獨立的協程(或一個線程?)以保留數據。 我不想持久性會阻止獲取更多數據。 -收到響應后,將檢查是否需要請求更多頁面才能獲取完整數據。 如果需要更多頁面,則將另一個任務添加到循環中以獲取下一頁。

我為一個最小的示例編寫了一些代碼,該代碼應提供我要實現的目標的框架:

import asyncio
import time 
import datetime
from random import random

sema = asyncio.Semaphore(2)

async def my_worker():
    async with sema:
        print("{}".format(datetime.datetime.now()))
        print("I'm going to fetch some data")
        result = await data_fetcher()

        print("I'm going to save data to disk")
        await write_result_to_disk(result)

        if random() > 0.5:
            print("I need to create and run a new worker here to fetch more data")

async def data_fetcher():
    await asyncio.sleep(3)
    return "Bla bla bla"

async def write_result_to_disk(result):
    await asyncio.sleep(3)
    print(result)

blah = [my_worker(), my_worker(), my_worker(), my_worker(), my_worker()]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(*blah))
print("All Workers Completed")
loop.close()

這似乎正確設置了信號燈並運行了工作程序,但是它留下了幾個問題未得到回答:

  • 首先,我如何動態地向循環中添加更多工作器(以獲取后續頁面)?
  • 我該如何處理持久性,以免阻止數據獲取?
  • 假設多個頁面需要在同一個文件中結束,我如何安全地從這些請求中收集所有數據,合並它們,然后在不阻止其他數據提取請求的情況下持久保存?

預先感謝您的任何幫助!

首先,我如何動態地向循環中添加更多工作器(以獲取后續頁面)?

您可以使用asyncio.ensure_future將新協程排隊到事件循環中。

我該如何處理持久性,以免阻止數據獲取?

如果您正在談論寫數據庫,那么這里有一些庫。 如果您正在談論寫入文件,那很棘手-本地文件IO幾乎總是阻塞,因此您必須將工作委派給單獨的線程。 幸運的是,asyncio為此提供了一個幫助器: loop.run_in_executor

假設多個頁面需要在同一個文件中結束,我如何安全地從這些請求中收集所有數據,合並它們,然后在不阻止其他數據提取請求的情況下持久保存?

這開始超出SO的一個好問題的范圍。 您應該為此閱讀不同的並發模式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM