首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python多处理进程在启动后立即死亡。

Python多处理进程在启动后立即死亡。
EN

Stack Overflow用户
提问于 2020-12-04 11:46:21
回答 2查看 538关注 0票数 1

我很难使用Python的“多处理”模块。我希望用简单的东西填充队列,并在队列不为空时打印内容,这将使我知道我的一个进程已经结束。

下面是一个很小的例子:

  1. 我创建了一个空队列q
  2. 我创建了一个进程列表( processes ),只要我的CPU允许,我就会立即启动列表中的每个进程(proc.start())。
  3. 每个进程的目标函数是一个非常简单的函数f,它首先等待2秒,然后在队列中写“hello”(这是它的唯一参数)。
  4. 之后,我每0.5秒检查一次,如果q不是空的(每当我的一个进程成功地执行f函数时,它都会收到一个“hello”),我还会检查我的进程是否处于活动状态。

我在这里面临两个问题:

  • 从第一次尝试开始,我所有的过程都不是活的;
  • 没有打印任何内容,这意味着队列q从未成功地接收到任何“hello”。

你会在下面找到我的代码。

代码语言:javascript
复制
# -*- coding: utf-8 -*-
"""
Created on Fri Dec  4 12:21:23 2020

@author: rbourgeon
"""
import multiprocessing as mp
import time


def f(q):
    time.sleep(2)
    q.put('hello')


pool_size = mp.cpu_count() - 1
print(f'pool_size is {pool_size}')

q = mp.Queue()

processes = []
num_active_processes = 0

# Starting processes
while len(processes) < pool_size:
    proc = mp.Process(target=f,
                      args=(q,)
                      )   
    processes.append(proc)
    proc.start()
    print(f'{len(processes)} jobs started')
    num_active_processes += 1

# Checking if queue is empty every 0.5 second. If not empty, we pop an element
# and we print it
    
for i in range(1, 100):
    print(f'\nAttempt #{i}')
    if not q.empty():
        print(q.get())
    time.sleep(0.5)
    print(processes)
    print([p.is_alive() for p in processes])

以下内容将打印到控制台:

代码语言:javascript
复制
pool_size is 7
1 jobs started
2 jobs started
3 jobs started
4 jobs started
5 jobs started
6 jobs started
7 jobs started

Attempt #1
[<Process(Process-8, stopped[1])>, <Process(Process-9, stopped[1])>, <Process(Process-10, stopped[1])>, <Process(Process-11, stopped[1])>, <Process(Process-12, stopped[1])>, <Process(Process-13, stopped[1])>, <Process(Process-14, stopped[1])>]
[False, False, False, False, False, False, False]

Attempt #2
[<Process(Process-8, stopped[1])>, <Process(Process-9, stopped[1])>, <Process(Process-10, stopped[1])>, <Process(Process-11, stopped[1])>, <Process(Process-12, stopped[1])>, <Process(Process-13, stopped[1])>, <Process(Process-14, stopped[1])>]
[False, False, False, False, False, False, False]

等等直到最后一次尝试。

这意味着( a)我的所有进程都在0.5秒( b)内死亡),同时,没有一个进程成功地执行函数f,因为"print“行从未执行过(因此队列是空的)。

EN

回答 2

Stack Overflow用户

发布于 2020-12-04 12:07:17

我发现了我的代码不能按预期工作的原因:启动进程的代码块if __name__ == '__main__':.应该封装在中

多处理模块的文档化说:

应该使用if __name__ == '__main__':保护程序的“入口点”。

这样做,代码工作正常。

票数 2
EN

Stack Overflow用户

发布于 2020-12-04 12:01:04

您的f函数不会输入任何作为工作人员运行的内容:一旦它运行最后一行,它就会结束并返回--这将关闭它所驻留的进程。

因此,预计在您的最后检查中不会有任何进程处于活动状态。

令人惊讶的是,您说调用方队列中没有显示该值--正如您所发现的,这是因为在Windows中,与启动子进程调用本身有关的代码只应该在主进程上运行(其方法是检查__name__变量是否等于"__main__") --实际上,您可能没有看到打印结果。我在这里运行了您的代码,它的工作原理与预期一样。请注意,您只需在每次“尝试”中打印一个队列元素。因为每个进程只会在队列中放置一个元素并退出,所以在前15次尝试中的8次之后(前4次尝试将在子进程处于2秒的“睡眠”中)之后打印出来,并且当进程结束时,不会看到后续打印。

如果您想让工作人员继续运行,那么您的目标函数中应该有一个while循环,它将尝试从队列和分派任务中读取消息。编写它并不难,但是Python已经在concurrent.futures库中为您完成了这一点:是的,使用这种方法,您可以创建一个由Python运行时保持活动的子进程池,而不是显式关闭它,并且可以在任何时候从主进程单独调用每个目标函数,重用该进程--而且该函数只是一个普通的Python函数--不需要循环、侦听队列等等…

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65143003

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档