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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.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_Python 2.7_Multiprocessing - Fatal编程技术网

Python多处理:如果进程';孩子们有孙子吗?

Python多处理:如果进程';孩子们有孙子吗?,python,python-2.7,multiprocessing,Python,Python 2.7,Multiprocessing,下面是我正在处理的一个玩具问题: import multiprocessing as mp def task2(): print "I am doing something important." def task1(): listOfProcesses = [] for i in range(5): process = mp.Process(target=task2) process.start() listOfPro

下面是我正在处理的一个玩具问题:

import multiprocessing as mp

def task2():
    print "I am doing something important."

def task1():
    listOfProcesses = []
    for i in range(5):
        process = mp.Process(target=task2)
        process.start()
        listOfProcesses.append(process)

def task0():
    listOfProcesses = []
    for i in range(5):
        process = mp.Process(target=task1)
        process.start()
        listOfProcesses.append(process)

if __name__ == '__main__':
    task0()
现在,我很难理解在这种情况下应该在何处调用join

如果我这样更改task0的定义:

def task0():
    listOfProcesses = []

    for i in range(5):
        process = mp.Process(target=task2)
        process.start()
        listOfProcesses.append(process)

    for process in listOfProcesses:
        process.join()
一切似乎都正常,但我不明白我到底在这里做什么<代码>任务1只启动其子级,而不加入它们。那么,加入
task0
task1
意味着什么呢?

在类Unix系统(Linux、BSD等)上,
mp.Process
实际上调用
os.fork
,而生成的进程对象的
join
方法调用
wait
(或一个变体)1等待它(即,等待特定进程,而不仅仅是任意进程)

fork
的子级只能由其父级等待,2因此
task0
可以等待每个
task1
,但不能等待任何
task1
task2
任务。同时,每个
task1
可以等待自己的
task2
任务,但不能等待任何其他
task1
任务

由于每个
task2
都非常短(并且每个进程在从其
target=
函数返回时退出),因此无论您是否显式地加入
join
,都很难在这里看到任何差异。您需要做一些更慢的事情(例如,
time.sleep()
或做一些实际工作)才能看到任何真正的差异


1实际调用是
os.waitpid()
;请参阅
multiprocessing/forking.py
。实际调用在
poll
函数中

2如果父进程在不等待其子进程的情况下退出,则这些子进程将被“孤立”并作为代理父进程传递给PID 1(init)。进程1循环调用
wait
(或等效程序)以清除它们



(Windows变体使用不同的调用,例如,它不能
fork
,而我不在Windows上工作,因此我不确定那里的实际情况。)

join
在概念上相当简单-
x.join
表示“当前线程(即进程)在
x
终止之前,无法继续执行此点。”

因此,一般来说,在所有工作人员完成工作之前,您不希望您的main线程通过某个点。由于您在主线程中执行
task0
,因此执行
join
会阻止主线程通过该点,直到所有工作人员完成为止(任务1和任务2都已完成

但是等等,我没有加入到任务1中! 没错。但是
task1
的进程在其所有
task2
完成之前不会终止。这与POSIX的概念有关-父进程在其所有子进程终止之前不会终止。因此,让我们看看这个简化示例的输出:

import multiprocessing as mp
from time import sleep

def task2():
    sleep(1)
    print "I am doing something important."

def task1():
    for i in range(2):
        process = mp.Process(target=task2)
        process.start()

    print 'task1 done'

def task0():
    process = mp.Process(target=task1)
    process.start()
    process.join()

if __name__ == '__main__':
    task0()
    print 'all done'
输出:

task1 done
I am doing something important.
I am doing something important.
all done
正如您所看到的,
task1
已经结束,但直到其子进程结束后才终止,这意味着
task0
中的
join
块正确地阻止了主线程终止,直到所有工作进程都终止

为了好玩,这里是运行原始脚本时的
ps jf
输出,没有
join
s,唯一的修改是
time。sleep
被扔进
task2
中,这样我就可以捕捉到它在运行:

 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
 6780  7385  7385  7385 pts/11    7677 Ss    1000   0:00 bash
 7385  7677  7677  7385 pts/11    7677 R+    1000   0:00  \_ ps jf
 6780  6866  6866  6866 pts/7     7646 Ss    1000   0:00 bash
 6866  7646  7646  6866 pts/7     7646 S+    1000   0:00  \_ python test
 7646  7647  7646  6866 pts/7     7646 S+    1000   0:00      \_ python test
 7647  7672  7646  6866 pts/7     7646 S+    1000   0:00      |   \_ python test
 7647  7673  7646  6866 pts/7     7646 S+    1000   0:00      |   \_ python test
 7647  7674  7646  6866 pts/7     7646 S+    1000   0:00      |   \_ python test
 7647  7675  7646  6866 pts/7     7646 S+    1000   0:00      |   \_ python test
 7647  7676  7646  6866 pts/7     7646 S+    1000   0:00      |   \_ python test
 7646  7648  7646  6866 pts/7     7646 S+    1000   0:00      \_ python test
 7648  7665  7646  6866 pts/7     7646 S+    1000   0:00      |   \_ python test
 7648  7666  7646  6866 pts/7     7646 S+    1000   0:00      |   \_ python test
 7648  7667  7646  6866 pts/7     7646 S+    1000   0:00      |   \_ python test
 7648  7668  7646  6866 pts/7     7646 S+    1000   0:00      |   \_ python test
 7648  7669  7646  6866 pts/7     7646 S+    1000   0:00      |   \_ python test
 7646  7649  7646  6866 pts/7     7646 S+    1000   0:00      \_ python test
 7649  7656  7646  6866 pts/7     7646 S+    1000   0:00      |   \_ python test
 7649  7657  7646  6866 pts/7     7646 S+    1000   0:00      |   \_ python test
 7649  7658  7646  6866 pts/7     7646 S+    1000   0:00      |   \_ python test
 7649  7659  7646  6866 pts/7     7646 S+    1000   0:00      |   \_ python test
 7649  7660  7646  6866 pts/7     7646 S+    1000   0:00      |   \_ python test
 7646  7650  7646  6866 pts/7     7646 S+    1000   0:00      \_ python test
 7650  7652  7646  6866 pts/7     7646 S+    1000   0:00      |   \_ python test
 7650  7653  7646  6866 pts/7     7646 S+    1000   0:00      |   \_ python test
 7650  7654  7646  6866 pts/7     7646 S+    1000   0:00      |   \_ python test
 7650  7655  7646  6866 pts/7     7646 S+    1000   0:00      |   \_ python test
 7650  7670  7646  6866 pts/7     7646 S+    1000   0:00      |   \_ python test
 7646  7651  7646  6866 pts/7     7646 S+    1000   0:00      \_ python test
 7651  7661  7646  6866 pts/7     7646 S+    1000   0:00          \_ python test
 7651  7662  7646  6866 pts/7     7646 S+    1000   0:00          \_ python test
 7651  7663  7646  6866 pts/7     7646 S+    1000   0:00          \_ python test
 7651  7664  7646  6866 pts/7     7646 S+    1000   0:00          \_ python test
 7651  7671  7646  6866 pts/7     7646 S+    1000   0:00          \_ python test
您可以看到,我们的主进程(执行
task0
)和“第一个子进程”(执行
task1
)仍然存在,尽管它们显然没有python代码可执行。它们也是同一进程组的所有成员(
TPGID

总结一下,伙计
所有这一切都是一种冗长的说法:
在主线程中加入
通常是您所需要的,因为您可以保证任何子进程都将在其子进程终止之前等待其子进程终止。

@roippi我输入了一个错误,我已经对其进行了修复,并添加了一点内容,以使我调用的
task0
变得清晰。