Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/332.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/svn/5.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
Python多处理进程在启动后立即死亡_Python_Multiprocessing - Fatal编程技术网

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

Python多处理进程在启动后立即死亡,python,multiprocessing,Python,Multiprocessing,我正在努力使用Python多处理模块。我想用简单的东西填充一个队列,并在队列不为空时打印东西,这会让我知道我的一个进程已经终止 您将在下面找到一个简单的示例: 我创建了一个空队列q 我创建了一个进程列表,只要我的CPU允许;我会在列表中的每个进程创建后立即启动proc.start 每个进程的目标函数是一个非常简单的函数f,它首先等待2秒钟,然后在队列中写入“hello”,这是它的唯一参数 之后,我每隔0.5秒检查一次,如果q不是空的,那么每当我的一个进程成功执行函数f时,它都会收到一个“hell

我正在努力使用Python多处理模块。我想用简单的东西填充一个队列,并在队列不为空时打印东西,这会让我知道我的一个进程已经终止

您将在下面找到一个简单的示例:

我创建了一个空队列q

我创建了一个进程列表,只要我的CPU允许;我会在列表中的每个进程创建后立即启动proc.start

每个进程的目标函数是一个非常简单的函数f,它首先等待2秒钟,然后在队列中写入“hello”,这是它的唯一参数

之后,我每隔0.5秒检查一次,如果q不是空的,那么每当我的一个进程成功执行函数f时,它都会收到一个“hello”,并且我还检查我的进程是否处于活动状态

我在这里面临两个问题:

从第一次尝试开始,我的所有进程都不是活动的; 从未打印任何内容,这意味着队列q从未成功接收任何“hello”。 你可以在下面找到我的代码

# -*- 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])
将以下内容打印到控制台:

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,因为打印行从未执行过,因此队列为空。

您的f函数不会保持任何工作进程的运行:一旦运行最后一行,它将结束并返回-这将关闭它所在的进程

因此,预计在最终检查中不会有任何流程处于活动状态

令人惊讶的是,您说该值没有显示在调用方队列中—正如您所发现的,这是因为在Windows中,与启动子进程调用本身相关的代码应该只在主进程上运行,而执行该操作的方法是检查uuuu name_uuu变量是否等于uuuu main_uuuu—实际上,很可能你只是没有看到印刷品。我已经在这里运行了您的代码,并且它按照预期工作。请注意,每次尝试只打印一个队列元素。由于每个进程将只在队列中放置一个元素并退出,因此您应该看到在前15次尝试中的8次之后打印hello。前4次尝试将在子进程处于2秒休眠状态时进行,并且在进程完成后不会打印

如果您想让worker保持运行,您应该在目标函数中有一个while循环,它将尝试从队列读取消息并分派任务。这并不难写,但Python已经在库中为您完成了:使用这种方法,您可以创建一个子流程池,在不显式关闭它的情况下,由Python运行库保持活动状态,并且可以随时从主流程单独调用您的每个目标函数,重用该进程—该函数只是一个普通的Python函数—无需循环、侦听队列等。

您的f函数不会保持任何工作进程的运行:一旦它运行最后一行,它将结束并返回—这将关闭它所处的进程

因此,预计在最终检查中不会有任何流程处于活动状态

令人惊讶的是,您说该值没有显示在调用方队列中—正如您所发现的,这是因为在Windows中,与启动子进程调用本身相关的代码应该只在主进程上运行,而执行该操作的方法是检查uuuu name_uuu变量是否等于uuuu main_uuuu—实际上,很可能你只是没有看到印刷品。我已经在这里运行了您的代码,并且它按照预期工作。请注意,每次尝试只打印一个队列元素。由于每个进程将只在队列中放置一个元素并退出,因此您应该看到在前15次尝试中的8次之后打印hello。前4次尝试将在子进程处于2秒休眠状态时进行,并且在进程完成后不会打印


如果您想让worker保持运行,您应该在目标函数中有一个while循环,它将尝试从队列读取消息并分派任务。这并不难写,但Python已经在库中为您完成了:使用这种方法,您可以创建一个子流程池,在不显式关闭它的情况下,由Python运行库保持活动状态,并且可以随时从主流程单独调用您的每个目标函数,重用进程-函数只是一个普通的Python函数-不需要循环、侦听队列等。

我找到了代码不能按预期工作的原因:启动进程的代码块应该封装在if u name_u=='u main_uu':

报告说:

我们应该使用if uuu name uuuuu=='\uuuuuu main_uuuuu'来保护程序的“入口点”:


o、 代码工作正常。

我找到了代码不能按预期工作的原因:启动进程的代码块应该封装在if _uname _uu=='_umain _u':

报告说:

我们应该使用if uuu name uuuuu=='\uuuuuu main_uuuuu'来保护程序的“入口点”:


这样做,代码就能正常工作。

控制台上打印的是什么?@JeffUK我编辑了我的文章来详细说明。你是否有可能在空闲状态下运行此程序?相关:似乎在空闲状态下,子进程没有机会将运行时错误打印到控制台上,因此你看不到任何东西,但在其他环境中,您将根据此链接获得运行时错误。我正在使用Spyder运行代码。我解决了这个问题,请看下面我自己的答案,这是因为我的主要代码块没有受到if name='main'的保护,控制台上打印的是什么?@JeffUK我编辑了我的帖子来详细说明。你是否有可能在空闲状态下运行此程序?相关:在空闲状态下,子进程似乎没有机会将运行时错误打印到控制台上,因此,您什么也看不到,但在其他环境中,您将根据此链接获得运行时错误。我解决了这个问题,请看下面我自己的答案,这是因为我的主要代码块没有受到if name=='main'的保护。在windows上需要if\uuuu name=='uuuuu main'`guard。在Linux、Mac Os和其他系统上,多处理模块使用一个不会再次启动Python脚本的fork调用-这就是为什么我的答案与此不同的原因,我在本例中重点讨论了其他问题。windows上需要if _uname __==_; main _ `保护。在Linux、Mac Os和其他系统上,多处理模块使用一个不会再次启动Python脚本的fork调用-这就是为什么我的答案与此不同的原因,我在这个示例中重点讨论了其他问题。感谢Windows/非Windows附加说明!事实上,我忘了提及我使用的操作系统。感谢您提供的Windows/非Windows附加说明!事实上,我忘了提到我正在使用的操作系统。