亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Asyncio python:如何在協程中調用對象方法?

Asyncio python:如何在協程中調用對象方法?

繁星點點滴滴 2023-02-07 16:55:58
我目前正在嘗試做這樣的事情:import asyncioclass Dummy:    def method(self):        return 1    def __str__(self):        return "THIS IS A DUMMY CLASS"async def start_doing():    asyncio.sleep(1)    return Dummyasync def do_something():    return start_doing().method()async def main():    a = asyncio.create_task(do_something())    b = asyncio.create_task(do_something())    results = await asyncio.gather(a, b)    print(results)asyncio.run(main())但我收到此錯誤:AttributeError: 'coroutine' object has no attribute 'method'這表明我無法在協程對象上調用我的方法。解決此問題的一種方法是執行以下操作:async def do_something():    return (await start_doing()).method()但我認為這樣做本質上就是讓代碼同步。你不是在創造未來,而是在等待你的工作完成do_something,然后繼續處理隊列中的下一項。awaitable當已經等待并且我的對象準備好時,我應該如何在將來調用對象方法?如何安排它在未來被調用?
查看完整描述

2 回答

?
達令說

TA貢獻1821條經驗 獲得超6個贊

等待調用,然后在返回類的實例上調用該方法。


async def start_doing():

    await asyncio.sleep(1)

    return Dummy



async def do_something():

    thing = await start_doing()

    return thing().method()

當等待對象已經等待并且我的對象已準備好時,我應該如何在將來調用對象方法?如何安排它在未來被調用?


看看我能不能弄對。


當您創建任務do_something時,它會被安排。

最終事件循環決定讓我們do_something開始。

do_something呼叫start_doing并等待它。

在do_something等待的過程中,事件循環將控制權從它手中奪走,讓其他事情發生。

在某些時間點start_doing被調度,開始,完成等待/休眠,返回對象

在等待/睡眠部分控制可能已通過事件循環轉移到其他任務

最終在do_something等待事件循環完成后將控制權/焦點交還給它。

暗示其他計劃任務已經完成或正在等待某事。

我真的不知道調度算法是什么,我認為它是一個循環事件,但它可能比這更智能。


查看完整回答
反對 回復 2023-02-07
?
動漫人物

TA貢獻1815條經驗 獲得超10個贊

要進一步擴展@wwii答案并解決有關阻塞風險的擔憂,await您可以使用以下功能f


import time

from datetime import datetime

import asyncio


start = datetime.now()


async def f(x, block_for=3):

    print(f"{x} IN     {ellapsed_time()}s")

    time.sleep(block_for)

    print(f"{x} AWAIT  {ellapsed_time()}s")

    await asyncio.sleep(x)

    print(f"{x} OUT    {ellapsed_time()}s")

    

def ellapsed_time():

    return (datetime.now() - start).seconds

    


asyncio.create_task(f(2))

asyncio.create_task(f(1))

哪個產生:


2 IN     0s

2 AWAIT  3s

1 IN     3s

1 AWAIT  6s

2 OUT    6s

1 OUT    7s

Untilawait被調用,f(2)正在阻塞(阻止任何其他任務被調度)。一旦我們調用await,我們就明確地通知調度程序我們正在等待某事(通常是 I/O,但這里只是“睡眠”)。類似地,在它調用之前f(1)阻止f(2)出去await。


如果我們刪除阻塞部分(阻塞 0s)f(1)將被重新安排到執行之前f(2),因此將首先完成:


>>> start = datetime.now()

>>> asyncio.create_task(f(2, block_for=0))

>>> asyncio.create_task(f(1, block_for=0))


2 IN     0s

2 AWAIT  0s

1 IN     0s

1 AWAIT  0s

1 OUT    1s

2 OUT    2s

最后,關于這部分:


......如何安排它在未來被調用?


你可以看看python中的asyncio.sleep()是怎么實現的?,它可能會幫助您更好地理解異步編程的工作原理。


查看完整回答
反對 回復 2023-02-07
  • 2 回答
  • 0 關注
  • 149 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號