簡體   English   中英

並發 HTTP 和 SQL 請求使用異步 Python 3

[英]Concurrent HTTP and SQL requests using async Python 3

第一次嘗試asyncioaiohttp 我有以下代碼從MySQL數據庫獲取GET請求的urls 獲取響應並將其推送到MySQL數據庫。

if __name__ == "__main__":
    database_name = 'db_name'
    company_name = 'company_name'

    my_db = Db(database=database_name) # wrapper class for mysql.connector
    urls_dict = my_db.get_rest_api_urls_for_specific_company(company_name=company_name)
    update_id = my_db.get_updateid()
    my_db.get_connection(dictionary=True)

    for url in urls_dict:
        url_id = url['id']
        url = url['url']
        table_name = my_db.make_sql_table_name_by_url(url)
        insert_query = my_db.get_sql_for_insert(table_name)
        r = requests.get(url=url).json() # make the request
        args = [json.dumps(r), update_id, url_id]
        my_db.db_execute_one(insert_query, args, close_conn=False)

    my_db.close_conn()

這工作正常,但要加快速度我怎樣才能asynchronously運行它?

我看過這里這里這里,但似乎無法理解它。

這是我根據@Raphael Medaer 的回答嘗試過的。

async def fetch(url):
    async with ClientSession() as session:
        async with session.request(method='GET', url=url) as response:
            json = await response.json()
            return json


async def process(url, update_id):
    table_name = await db.make_sql_table_name_by_url(url)
    result = await fetch(url)
    print(url, result)

if __name__ == "__main__":
    """Get urls from DB"""
    db = Db(database="fuse_src")
    urls = db.get_rest_api_urls()  # This returns list of dictionary
    update_id = db.get_updateid()
    url_list = []
    for url in urls:
        url_list.append(url['url'])
    print(update_id)
    asyncio.get_event_loop().run_until_complete(
        asyncio.gather(*[process(url, update_id) for url in url_list]))

我在process方法中遇到錯誤:

TypeError: object str can't be used in 'await' expression

不確定是什么問題?

任何特定於此的代碼示例都將受到高度贊賞。

使此代碼異步根本不會加快速度。 除非您考慮“並行”運行部分代碼。 例如,您可以“同時”運行多個(SQL 或 HTTP)查詢。 通過進行異步編程,您將不會“同時”執行代碼。 盡管在等待 IOs 時,您將受益於長 IO 任務來執行代碼的其他部分。

首先,您必須使用異步庫(而不是同步庫)。

  • mysql.connector可以被 aio-libs 中的aiomysql替換。
  • requests可以替換為aiohttp

要“並行”執行多個異步任務(例如, for url in urls_dict:的循環),您必須仔細閱讀異步任務和 function gather

我不會以異步方式(重新)編寫您的代碼,但是這里有幾行偽代碼可以幫助您:

async def process(url):
    result = await fetch(url)
    await db.commit(result)

if __name__ == "__main__":
    db = MyDbConnection()
    urls = await db.fetch_all_urls()

    asyncio.get_event_loop().run_until_complete(
        asyncio.gather(*[process(url) for url in urls]))

暫無
暫無

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

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