Python3.7中的Fire、Forget和Return值

2024-04-28 23:32:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我有以下场景: 我有一个python服务器,在接收到请求时,需要解析一些信息,尽快将结果返回给用户,然后自己清理。 我试着用以下逻辑来设计它:

Consumer: *==*   (wait for result)   *====(continue running)=====...
              \                     / return
Producer:      *======(prase)====*=*
                                  \
Cleanup:                           *==========*

我一直在尝试使用异步任务和协程来实现这个场景,但没有效果。我尝试过的每一件事最终要么是制作人在返回前等待清理工作完成,要么是返回时终止了清理工作。 理论上,我可以让用户在向用户显示结果后调用cleanup,但我拒绝相信Python不知道如何“启动并忘记”并返回。你知道吗

例如,此代码:

import asyncio

async def Slowpoke():
    print("I see you shiver with antici...")
    await asyncio.sleep(3)
    print("...pation!")

async def main():
    task = asyncio.create_task(Slowpoke())
    return "Hi!"

if __name__ == "__main__":
    print(asyncio.run(main()))
    while True:
        pass

退货:

I see you shiver with antici...
Hi!

而且永远也到不了...pation。你知道吗

我错过了什么?你知道吗


Tags: 用户youasyncioasyncreturnmaindefwith
3条回答

我设法用线程而不是异步方式让它工作:

import threading
import time

def Slowpoke():
    print("I see you shiver with antici...")
    time.sleep(3)
    print("...pation")

def Rocky():
    t = threading.Thread(name="thread", target=Slowpoke)
    t.setDaemon(True)
    t.start()
    time.sleep(1)
    return "HI!"

if __name__ == "__main__":
    print(Rocky())
    while True:
        time.sleep(1)

asyncio似乎并不特别适合这个问题。您可能需要简单的线程:

其原因是,当父任务完成时,您的任务被终止。通过抛出一个daemon线程,您的任务将继续运行,直到它完成,或者直到程序退出。你知道吗

import threading
import time

def Slowpoke():
    try:
        print("I see you shiver with antici...")
        time.sleep(3)
        print("...pation!")
    except:
        print("Yup")
        raise Exception()

def main():
    task = threading.Thread(target=Slowpoke)
    task.daemon = True
    task.start()
    return "Hi!"

if __name__ == "__main__":
    print(main())
    while True:
        pass

^{}。。。你知道吗

[...] creates a new event loop and closes it at the end. [...]

在执行main期间,用task包装的coro没有机会完成。
如果返回Task对象并打印它,您将看到它处于取消状态:

async def main():
    task = asyncio.create_task(Slowpoke())
    # return "Hi!"
    return task

if __name__ == "__main__":
    print(asyncio.run(main()))

# I see you shiver with antici...
# <Task cancelled coro=<Slowpoke() done, defined at [...]>>

在创建和安排任务(并打印'Hi!')之后main结束时,事件循环将关闭,这将导致其中所有正在运行的任务被取消。你知道吗

您需要保持事件循环运行,直到任务完成为止,例如,通过await将其放入main

async def main():
    task = asyncio.create_task(Slowpoke())
    await task
    return task

if __name__ == "__main__":
    print(asyncio.run(main()))

# I see you shiver with antici...
# ...pation!
# <Task finished coro=<Slowpoke() done, defined at [..]> result=None>

相关问题 更多 >