python创建子进程的几种常用方式(fork, Process,进程池)

linux下使用fork()创建子进程

Linux 操作系统提供了一个 fork() 函数用来创建子进程,这个函数很特殊,调用一次,返回两次,因为操作系统是将当前的进程(父进程)复制了一份(子进程),然后分别在父进程和子进程内返回。子进程永远返回0,而父进程返回子进程的 PID(大于0)。我们可以通过判断返回值是不是 0 来判断当前是在父进程还是子进程中执行。

在 Python 中同样提供了 fork() 函数,此函数位于 os 模块下。

例子:

import os
import time

ret = os.fork()         #创建了一个子进程
if ret == 0:        #子进程
    while True:
        print("-------1--------")
        time.sleep(1)

else:               #父进程
    while True:
        print("-------2--------")
        time.sleep(1)

输出结果为:

-------2--------
-------1--------
-------1--------
-------2--------
-------1--------
-------2--------
-------1--------
-------2--------
-------1--------
-------2--------
-------1--------
-------2--------
-------1--------
-------2--------

无限循环。。。。。。(注:子进程和父进程的执行顺序不确定,即1和2输出顺序不一定,由操作系统的调度算法确定)

注意:如果父进程结束,子进程也跟着结束
如程序:

import os
import time

ret = os.fork()
if ret == 0:
    while True:
        print("---1-----")
        time.sleep(1)

else:
    print("---2-----")

输出结果为:

---2-----
---1-----

使用Process创建子进程

linux下可以使用fork创建子进程,但windows下不支持fork函数,但可以使用Process创建子进程

注意:与fork不同的是,主进程会等待Process子进程完成后结束。

Process语法结构如下:

Process([group [, target [, name [, args [, kwargs]]]]])

target:表示这个进程实例所调用对象;

args:表示调用对象的位置参数元组;

kwargs:表示调用对象的关键字参数字典;

name:为当前进程实例的别名;

group:大多数情况下用不到;

Process类常用方法:

is_alive():判断进程实例是否还在执行;

join([timeout]):是否等待进程实例执行结束,或等待多少秒;

start():启动进程实例(创建子进程);

run():如果没有给定target参数,对这个对象调用start()方法时,就将执行对象中的run()方法;

terminate():不管任务是否完成,立即终止;

Process类常用属性:

name:当前进程实例别名,默认为Process-N,N为从1开始递增的整数;

pid:当前进程实例的PID值;

from multiprocessing import Process
import time
import random

def test():
    for i in range(1,5):
        print("---%d---"%i)
        time.sleep(1)

p = Process(target=test)
p.start()   #让这个进程开始执行test函数里面的代码

p.join()     #等进程p结束之后,才会继续向下走
print("---main----")

输出结果为:

---1---
---2---
---3---
---4---
---main----

进程池创建子进程

当需要创建的子进程数量不多时,可以直接利用multiprocessing中的Process动态成生多个进程,但如果是上百甚至上千个目标,手动的去创建进程的工作量巨大,此时就可以用到multiprocessing模块提供的Pool方法。

初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来执行.

multiprocessing.Pool常用函数解析:

apply_async(func[, args[, kwds]]) :使用非阻塞方式调用func(并行执行,堵塞方式必须等待上一个进程退出才能执行下一个进程),args为传递给func的参数列表,kwds为传递给func的关键字参数列表;

apply(func[, args[, kwds]]):使用阻塞方式调用func

close():关闭Pool,使其不再接受新的任务;

terminate():不管任务是否完成,立即终止;

join():主进程阻塞,等待子进程的退出, 必须在close或terminate之后使用;

程序(非阻塞方式):

from multiprocessing import Pool
import os
import time

def worker(num):
    for i in range(2):
        print("===pid=%d===num=%d"%(os.getpid(), num))
        time.sleep(1)

pool = Pool(3)  #定义一个进程池,最大进程数3

for i in range(5):
    print("---%d---"%i)
    pool.apply_async(worker, [i,])    #使用非阻塞方式调用func(并行执行,堵塞方式必须
                                      #等待上一个进程退出才能执行下一个进程)

print("---start----")
pool.close()    #关闭进程池,关闭后pool不能再添加新的请求
pool.join()     #等待pool中所有子进程执行完成,必须放在close语句之后
print("---end----")

输出:

---0---
---1---
---2---
---3---
---4---
---start----
===pid=24958===num=0
===pid=24959===num=1
===pid=24960===num=2
===pid=24958===num=0
===pid=24960===num=2
===pid=24959===num=1
===pid=24960===num=3
===pid=24958===num=4
===pid=24960===num=3
===pid=24958===num=4
---end----

程序(阻塞方式):

from multiprocessing import Pool
import os
import time

def worker(num):
    for i in range(2):
        print("===pid=%d===num=%d"%(os.getpid(), num))
        time.sleep(1)

pool = Pool(3)  #定义一个进程池,最大进程数3

for i in range(5):
    print("---%d---"%i)
    pool.apply(worker, [i,])    #使用非阻塞方式调用func(并行执行,堵塞方式必须
                                      #等待上一个进程退出才能执行下一个进程)

print("---start----")
pool.close()    #关闭进程池,关闭后pool不能再添加新的请求
pool.join()     #等待pool中所有子进程执行完成,必须放在close语句之后
print("---end----")

输出:

---0---
===pid=24999===num=0
===pid=24999===num=0
---1---
===pid=25000===num=1
===pid=25000===num=1
---2---
===pid=25001===num=2
===pid=25001===num=2
---3---
===pid=24999===num=3
===pid=24999===num=3
---4---
===pid=25000===num=4
===pid=25000===num=4
---start----
---end----

注意:进程池和fork()一样,不会等待子程序结束

例子:

from multiprocessing import Pool
import os
import time

def worker():
    for i in range(2):
        print("===pid=%d==="%os.getpid())
        time.sleep(1)

pool = Pool(3)  #定义一个进程池,最大进程数3

for i in range(5):
    print("---%d---"%i)
    pool.apply_async(worker)    #使用非阻塞方式调用func(并行执行,堵塞方式必须
                                #等待上一个进程退出才能执行下一个进程)

输出:

---0---
---1---
---2---
---3---
---4---

猜你喜欢

转载自blog.csdn.net/duke10/article/details/79861201