第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

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

在異步生成器函數(shù)中從托兒所內(nèi)部產(chǎn)生 yield 不好嗎?

在異步生成器函數(shù)中從托兒所內(nèi)部產(chǎn)生 yield 不好嗎?

呼如林 2023-05-09 09:49:43
有人告訴我下面的代碼是不安全的,因為它不允許有一個從 nursery 內(nèi)部產(chǎn)生的異步生成器,除非它是一個異步上下文管理器。T = TypeVar('T')async def delay(interval: float, source: AsyncIterable[T]) -> AsyncIterable[T]:    """Delays each item in source by an interval.    Received items are temporarily stored in an unbounded queue, along with a timestamp, using    a background task. The foreground task takes items from the queue, and waits until the    item is older than the given interval and then yields it."""    send_channel, receive_channel = trio.open_memory_channel(math.inf)    async def pull_task():        async with aclosing(source) as agen:            async for item in agen:                send_channel.send_nowait((item, trio.current_time() + interval))    async with trio.open_nursery() as nursery:        nursery.start_soon(pull_task)        async with receive_channel:            async for item, timestamp in receive_channel:                now = trio.current_time()                if timestamp > now:                    await trio.sleep(timestamp - now)                yield item我很難理解這怎么可能會破裂。如果有人可以提供使用這個確切的生成器函數(shù)的示例代碼,它證明了不安全性,我們將不勝感激和獎勵。上述代碼的目標(biāo)是在不施加任何背壓的情況下延遲異步序列的處理。如果您能證明此代碼無法像我預(yù)期的那樣工作,那我們也將不勝感激。
查看完整描述

1 回答

?
慕姐8265434

TA貢獻1813條經(jīng)驗 獲得超2個贊

不幸的是,這是正確的——yield在 nursery 或 cancel 范圍內(nèi)不受支持,除非在用于@contextlib.asynccontextmanager創(chuàng)建異步上下文管理器或編寫異步 pytest fixture 的狹窄情況下。

有幾個原因。其中一些是技術(shù)性的:Trio 必須跟蹤哪些 nurseries/cancel 作用域當(dāng)前在堆棧中處于“活動”狀態(tài),當(dāng)你離開yield一個時,它會破壞嵌套,Trio 無法知道你已經(jīng)完成這。(庫無法檢測出yield上下文管理器。)

但還有一個根本的、無法解決的原因,那就是Trio和結(jié)構(gòu)化并發(fā)的整個思想是,每個任務(wù)都“屬于”一個父任務(wù),如果子任務(wù)崩潰,父任務(wù)可以收到通知。但是當(dāng)你yield在一個生成器中時,生成器框架會被凍結(jié)并與當(dāng)前任務(wù)分離——它可能會在另一個任務(wù)中恢復(fù),或者根本不會恢復(fù)。所以當(dāng)你yield,這打破了托兒所中所有子任務(wù)和他們父母之間的聯(lián)系。只是沒有辦法將其與結(jié)構(gòu)化并發(fā)的原則相協(xié)調(diào)。

如果我運行以下


async def arange(*args):

? ? for val in range(*args):

? ? ? ? yield val


async def break_it():

? ? async with aclosing(delay(0, arange(3))) as aiter:

? ? ? ? with trio.move_on_after(1):

? ? ? ? ? ? async for value in aiter:

? ? ? ? ? ? ? ? await trio.sleep(0.4)

? ? ? ? ? ? ? ? print(value)


trio.run(break_it)

然后我得到


RuntimeError: Cancel scope stack corrupted: attempted to exit

<trio.CancelScope at 0x7f364621c280, active, cancelled> in <Task

'__main__.break_it' at 0x7f36462152b0> that's still within its child

<trio.CancelScope at 0x7f364621c400, active>


This is probably a bug in your code, that has caused Trio's internal

state to become corrupted. We'll do our best to recover, but from now

on there are no guarantees.


Typically this is caused by one of the following:

? - yielding within a generator or async generator that's opened a cancel

? ? scope or nursery (unless the generator is a @contextmanager or

? ? @asynccontextmanager); see https://github.com/python-trio/trio/issues/638 [...]

通過更改超時和延遲,使超時在生成器內(nèi)部而不是在生成器外部過期,我還能夠得到一個不同的錯誤:trio.MultiError: Cancelled(), GeneratorExit() raised out of aclosing()


查看完整回答
反對 回復(fù) 2023-05-09
  • 1 回答
  • 0 關(guān)注
  • 139 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號