我在除錯問題時遇到了一些麻煩,我有一個 asyncio 專案,我希望它能夠正常關閉。
import asyncio
import signal
async def clean_loop(signal, loop):
print("something")
tasks = [t for t in asyncio.all_tasks() if t is not
asyncio.current_task()]
[task.cancel() for task in tasks]
await asyncio.gather(*tasks, return_exceptions=True)
loop.stop()
def main():
loop = asyncio.get_event_loop()
signals = (signal.SIGTERM, signal.SIGINT)
for s in signals:
loop.add_signal_handler(s, lambda s=s: asyncio.create_task(clean_loop(s, loop)))
task = loop.create_task(run(some_code))
loop.call_later(60, task.cancel)
try:
loop.run_until_complete(task)
except asyncio.CancelledError:
pass
finally:
loop.close()
if __name__ == "__main__":
main()
當我運行我的代碼并從不同的螢屏發送一個 KeyboardInterrupt 或 TERM 信號時,似乎什么都沒有發生,而且看起來好像沒有呼叫 clean_loop。
編輯:我認為我能夠更多地隔離問題,我正在運行的代碼some_code
有一個無限回圈并在其中包含另一個asyncio.gather(*tasks)
,當我將其注釋掉時,我能夠捕捉到信號并且 clean_loop 運行。誰能解釋為什么會發生這種沖突?
uj5u.com熱心網友回復:
如果您使用的是類 Unix 系統,
"""為信號添加處理程式。僅限 UNIX。
它應該可以正常作業。唯一的事情是clean_loop
它本身就是一個被摧毀的任務,loop.stop()
因此你會看到:
Task was destroyed but it is pending!
task: <Task pending name='Task-2' coro=<clean_loop() running at ...> wait_for=<_GatheringFuture finished result=[CancelledError('')]>>
但它不應該很重要,因為它只是用于cancel
任務。
我做了一些與實際問題無關的細微更改:
import asyncio
import signal
async def run():
for i in range(4):
print(i)
await asyncio.sleep(2)
async def clean_loop(signal, loop):
print("-----------------------handling signal")
tasks = asyncio.all_tasks() - {asyncio.current_task()}
for task in tasks:
task.cancel()
print("--------------------------reached here")
await asyncio.gather(*tasks, return_exceptions=True)
loop.stop()
def main():
loop = asyncio.new_event_loop()
signals = (signal.SIGTERM, signal.SIGINT)
for s in signals:
loop.add_signal_handler(s, lambda s=s: asyncio.create_task(clean_loop(s, loop)))
task = loop.create_task(run())
loop.call_later(60, task.cancel)
try:
loop.run_until_complete(task)
except asyncio.CancelledError:
pass
finally:
loop.close()
if __name__ == "__main__":
main()
輸出:
0
1
2
^C-----------------------handling signal
--------------------------reached here
Task was destroyed but it is pending!
task: <Task pending name='Task-2' coro=<clean_loop() running at ...> wait_for=<_GatheringFuture finished result=[CancelledError('')]>>
根據您的編輯:
add_signal_handler的檔案說:
回呼將由 loop 呼叫,以及該事件回圈的其他排隊回呼和可運行協程。
就像其他協程一樣,它應該由回圈以協作的方式呼叫。換句話說,協程應該將控制權交還給事件回圈,以便事件回圈可以運行另一個協程。
在您的情況下,您的具有無限回圈的協程會阻止事件回圈運行另一個協程,尤其是通過注冊的回呼add_signal_handler
。不合作!這就是為什么你雖然它沒有作業。它在佇列中閑置等待運行。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/508486.html
標籤:Python python-3.x 异步 信号 蟒蛇异步
下一篇:異步通道無法停止