当前位置: 首页 > 知识库问答 >
问题:

python - eventlet 如何保证任务都运行完了,才退出进程?

叶福
2023-05-10
from eventlet import monkey_patch
monkey_patch()

import eventlet
import time
from loguru import logger


def run(task_id: int):
    logger.debug(f'开始执行任务: {task_id}')
    time.sleep(3)
    logger.debug(f'开始执行任务: {task_id}')


eventlet.spawn_n(run,1)
eventlet.spawn_n(run,2)

写了上面的代码,但是有一个问题,就是运行后,程序就退出了,都没有执行 run

所以,如何保证任务都运行完了,才退出进程?


chatGPT 给的方法不行,不能运行

图片.png

╰─➤  time python main.py
Traceback (most recent call last):
  File "/Users/ponponon/Desktop/code/me/ideaboom/main.py", line 18, in <module>
    eventlet.greenthread.waitall()
AttributeError: module 'eventlet.greenthread' has no attribute 'waitall'
python main.py  0.49s user 0.07s system 79% cpu 0.702 total

共有2个答案

隆宏爽
2023-05-10

官方api给到了函数的说明,spawn_n 是快速执行,没有返回值的,所以它不知道什么时候你所调用的func程序会执行结束。

eventlet.spawn_n(func, args, *kw)

The same as spawn(), but it’s not possible to know how the function terminated (i.e. no return value or exceptions). This makes execution faster. See spawn_n for more details.

方案一:你可以使用 eventletEvent 控制。

from eventlet import Event, monkey_patch

monkey_patch()

import time

import eventlet
from loguru import logger

event = Event()


def run(task_id: int):
    logger.debug(f"开始执行任务: {task_id}")
    time.sleep(3)
    logger.debug(f"开始执行任务: {task_id}")
    if event.has_result():
        event.reset()
    event.send(True)


eventlet.spawn_n(run, 1)
eventlet.spawn_n(run, 2)

event.wait()

方案二:你不要使用 spawn_n,转而使用 spawn 方法。

因为 spawn 会返回一个 GreenThread 对象,并且你可以通过这个返回拿到对应 func 的返回值。

eventlet.spawn(func, args, *kw)

This launches a greenthread to call func. Spawning off multiple greenthreads gets work done in parallel. The return value from spawn is a greenthread.GreenThread object, which can be used to retrieve the return value of func. See spawn for more details.
from eventlet import monkey_patch

monkey_patch()

import time

import eventlet
from loguru import logger


def run(task_id: int):
    logger.debug(f"开始执行任务: {task_id}")
    time.sleep(3)
    logger.debug(f"开始执行任务: {task_id}")


res1 = eventlet.spawn(run, 1)
res2 = eventlet.spawn(run, 2)

res1.wait()
res2.wait()

方案三: 使用GreenPool去控制, waitall() 控制所有任务完成后退出

from eventlet import GreenPool, monkey_patch

monkey_patch()

import time

from loguru import logger

pool = GreenPool()


def run(task_id: int):
    logger.debug(f"开始执行任务: {task_id}")
    time.sleep(3)
    logger.debug(f"开始执行任务: {task_id}")


res1 = pool.spawn_n(run, 1)
res2 = pool.spawn_n(run, 2)

pool.waitall()
商燕七
2023-05-10
import eventlet

def run(task_id):
    print(f'开始执行任务: {task_id}')
    eventlet.sleep(3)
    print(f'结束执行任务: {task_id}')

pool = eventlet.greenpool.GreenPool()
pool.spawn_n(run, 1)
pool.spawn_n(run, 2)
pool.waitall() # 等待所有协程执行完毕


print('所有任务已完成')
 类似资料:
  • 我有一大堆Scalaz任务。创建方式如下: 我希望这些任务并行运行。以随机顺序打印数字,不要花5秒钟(每个任务有50个任务和100毫升睡眠)。 但是,很明显,每个任务需要100毫秒,所有任务都需要5秒钟,并且创建的列表是有序的。 如何并行运行它们?任务在哪里运行线程?

  • 我下载了封装在zip文件中的proGuard,并将其解压缩到我的硬盘上。我没有以任何方式安装它(因为我不知道如何安装)。然后,我将添加到我的project.properties文件中。然后我做了一个“导出Android应用程序”,完全期待eclipse抱怨它不知道我的proGuard安装在哪里,但没有抱怨。事实上,一个新的apk文件出现在我的keystore中,一组文件(dump.txt等)出现在

  • 问题内容: 我正在使用ProcessBuilder启动子进程,并且如果父进程确实需要退出子进程。在正常情况下,我的代码可以正确阻止孩子。但是,如果我导致操作系统杀死父进程,则子进程将继续运行。 有什么方法可以将子进程“绑定”到父进程,以便在父进程被杀死时退出? 问题答案: 子进程与其父进程之间没有联系。他们可能彼此知道进程ID,但是它们之间没有硬连接。您在谈论孤立过程。这是操作系统级别的问题。意味

  • 问题内容: 因此,我注意到在等待命令完成之后再继续执行python脚本时,除了使用之外,我无法获取标准输出。是否有其他替代函数调用会等到完成?(我也尝试过) 注意:我正试图避免打电话 我的输出: 注意:我正在尝试与此。 问题答案: 我正在使用以下构造,尽管您可能要避免使用。这将为您提供任何命令的输出和错误消息,以及错误代码:

  • 所以我注意到虽然它在继续处理python脚本之前等待命令完成,但除了使用之外,我没有办法获得stdout。是否有其他的函数调用会等待它完成?(我还尝试了) 注意:我正在尝试避免调用

  • 问题内容: 从IntelliJ-Idea启动spring-boot应用程序时遇到问题。通过终端运行应用程序时,我没有这个问题。 我认为此警告不是造成此警告的原因。可能是什么原因? 问题答案: 删除 提供 的 spring-boot-starter-tomcat 依赖关系范围对我有帮助。