Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python3.7中的激发、遗忘和返回值_Python_Python Asyncio_Python 3.7_Producer Consumer_Fire And Forget - Fatal编程技术网

Python3.7中的激发、遗忘和返回值

Python3.7中的激发、遗忘和返回值,python,python-asyncio,python-3.7,producer-consumer,fire-and-forget,Python,Python Asyncio,Python 3.7,Producer Consumer,Fire And Forget,我有以下情况: 我有一个python服务器,在接收到请求时,需要解析一些信息,尽快将结果返回给用户,然后自己清理。 我尝试使用以下逻辑进行设计: Consumer: *==* (wait for result) *====(continue running)=====... \ / return Producer: *======(prase)====*=*

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

Consumer: *==*   (wait for result)   *====(continue running)=====...
              \                     / return
Producer:      *======(prase)====*=*
                                  \
Cleanup:                           *==========*
我一直在尝试使用异步任务和协同程序来实现这个场景,但没有效果。我尝试的每一件事最终要么是制作人在返回之前等待清理工作完成,要么是返回导致清理工作失败。 理论上,我可以让消费者在向用户显示结果后调用cleanup,但我不相信Python不知道如何“触发并忘记”并返回

例如,此代码:

导入异步IO
异步def Slowpoke():
打印(“我看到你因安提西而颤抖……”)
等待asyncio.sleep(3)
打印(“…打印!”)
异步def main():
task=asyncio.create_任务(Slowpoke())
回答“嗨!”
如果名称=“\uuuuu main\uuuuuuuu”:
打印(asyncio.run(main()))
尽管如此:
通过
返回:

I see you shiver with antici...
Hi!
而且永远也不会到达
…或

我错过了什么

[…]创建一个新的事件循环,并在结束时将其关闭。[……]

在执行
main

如果返回
任务
对象并打印它,您将看到它处于取消状态:

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 [...]>>

我成功地使用线程而不是异步IO使其工作:

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
似乎并不特别适合这个问题。您可能需要简单的线程:

原因是,当家长完成任务时,您的任务被终止。通过抛出一个
守护进程
线程,任务将继续运行,直到完成,或者直到程序退出

导入线程
导入时间
def Slowpoke():
尝试:
打印(“我看到你因安提西而颤抖……”)
时间。睡眠(3)
打印(“…打印!”)
除:
打印(“是”)
引发异常()
def main():
task=threading.Thread(目标=Slowpoke)
task.daemon=True
task.start()
回答“嗨!”
如果名称=“\uuuuu main\uuuuuuuu”:
打印(main())
尽管如此:
通过
(我希望我正确理解了你的问题。ASCII图像和文本描述在我脑海中并不完全一致。
“嗨!”
是结果,
“Antici..pation”
是清理,对吗?顺便说一句,我也喜欢那部音乐剧)

一种可能的基于asyncio的解决方案是尽快返回结果。返回将终止任务,这就是为什么需要启动并忘记清理。它必须附带停机代码,等待所有清理完成

import asyncio

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

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

async def start_stop():
    # you can create multiple tasks to serve multiple requests
    task = asyncio.create_task(main())
    print(await task)

    # after the last request wait for cleanups to finish
    this_task = asyncio.current_task()
    all_tasks = [ 
        task for task in asyncio.all_tasks()
        if task is not this_task]
    await asyncio.wait(all_tasks)

if __name__ == "__main__":
    asyncio.run(start_stop())

另一个解决方案是使用其他方法(而不是返回)将结果传递给等待的任务,以便在解析之后立即开始清理。未来被认为是低水平的,但这里有一个例子

import asyncio

async def main(fut):
    fut.set_result("Hi!")
    # result delivered, continue with cleanup
    print("I see you shiver with antici...")
    await asyncio.sleep(3)
    print("...pation!")

async def start_stop():
    fut = asyncio.get_event_loop().create_future()
    task = asyncio.create_task(main(fut))
    print(await fut)

    this_task = asyncio.current_task()
    all_tasks = [ 
        task for task in asyncio.all_tasks()
        if task is not this_task]
    await asyncio.wait(all_tasks)

if __name__ == "__main__":
    asyncio.run(start_stop())

当您可能想
永远运行_()
OP想要不等待地返回任务时,您正在运行主循环直到完成。是的,关键是返回值。不过,我确实找到了一个解决方案——使用TheReading.Oops,我为时已晚,hahaI添加了一个简单的解释,但您可能想稍微研究一下线程,以了解为什么您的任务在此之前会停止
import asyncio

async def main(fut):
    fut.set_result("Hi!")
    # result delivered, continue with cleanup
    print("I see you shiver with antici...")
    await asyncio.sleep(3)
    print("...pation!")

async def start_stop():
    fut = asyncio.get_event_loop().create_future()
    task = asyncio.create_task(main(fut))
    print(await fut)

    this_task = asyncio.current_task()
    all_tasks = [ 
        task for task in asyncio.all_tasks()
        if task is not this_task]
    await asyncio.wait(all_tasks)

if __name__ == "__main__":
    asyncio.run(start_stop())