Python多进程

在Unix/Linux操作系统下,提供了一个fork()系统函数,它非常特殊

  1. 普通函数调用,调用一次返回一次,但是fork()函数,调用一次,返回两次,因为操作系统自动把当前进程(称为父进程),复制了一份(称为子进程),然后分别在父进程和子进程内返回。
  2. 子进程永远返回0,而父进程返回子进程的ID
  3. 一个父进程可以fork出多个子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用getppid()就可以拿到父进程的ID
  4. 父进程、子进程执行的顺序没有规律,完全取决于操作系统的调度算法
  5. 各个进程有独立的运行空间,不共享全局变量
  6. 有时会因父进程提前退出,子进程的父进程和开始的不一致
import os

pid = os.fork()

if pid < 0:
    print("fork()调用失败")
elif pid == 0:
    print("子进程%s,父进程%s"(os.getpid(), os.getppid()))
    #子进程在系统的pid不为0
else:
    print("父进程%s,子进程%s"(os.getpid(), pid))
    #父进程返回子进程的ID
输出:
我是父进程1653,我的子进程1654
我是子进程1654,我的父进程1653

multiprocessing模块是跨平台版本的多进程模块,模块提供了一个Process类来代表一个进程。

创建子进程时,只需要传入一个执行函数和函数的参数,创建一个Process实例,用start()方法启动,这样创建的进程比fork()还简单。

  • Process([group[,target[,name[,args[,kargs]]]]])
  • target:表示这个进程实例所调用的对象
  • args:表示调用这个对象的位置和参数元组
  • kwargs:表示调用对象的关键字参数字典
  • group:多数情况用不到
  • start():启动进程
  • join():此方法等待子进程结束后再继续往下进行,通常用于进程同步

Process类常用方法

  • is_alive():判断进程是否还在执行
  • join([timeout]):是否等待进程实例执行结束,或等待多少秒
  • run():如果没给定target参数,这个对象调用start()方法时,执行对象中的run()方法,可以重写
  • terminate():不管任务是否完成,立即终止

Process类常用属性

  • name:当前进程实例别名,默认为Process-N,N为从1开始递增的整数
  • pid:当前进程实例的pid值
#coding = utf-8
from multiprocessing import Process
import os
import time

def run_proc(name):
    time.sleep(3)
    print("子进程运行中,name=%s,pid=%s,父进程=%s"%(name,os.getppid(),os.getppid()))


if __name__ == '__main__':
    print("父进程是%s"%os.getpid())
    p = Process(target=run_proc,args=('test',))
    print("子进程即将运行")
    p.start()#启动进程
    p.join()#阻塞当前进程,直到调用join方法的那个进程执行完,再继续执行当前进程
    print("子进程已结束")
#
from multiprocessing import Process
import os
import time

class MyProcess(Process):
    def __init__(self,interval):
        super().__init__()
        self.interval = interval

    def run(self):
        print("子进程")
        startTime = time.time()
        time.sleep(self.interval)
        stopTime = time.time()
        print("子进程id:%s,父进程id:%s,共执行多少秒%s"%(os.getppid(),os.getppid(),stopTime-startTime))

if __name__ == "__main__":#不加程序会出问题
    print("主进程")
    startTime = time.time()
    p = MyProcess(2)
    p.start()
    p.join()
    stopTime = time.time()
    print("子进程结束,花费了%s秒"%(stopTime-startTime))

当需要创建的子进程数量不多时,可以利用multiprocessing的Process动态生成多个进程,单数如果是成百上千个,可以使用multiprocessing模块提供的Pool方法

初始化进程时,可以指定有个最大进程数,当池中的进程数达到最大值时,该请求就会等待,直到池中有进程结束,才会创建新的进程来执行。

from multiprocessing import Pool
import os
import time
import random
#进程类
def worker(msg):
    t_start = time.time()
    print("%s开始执行,执行进程id为%s,父进程id为%s"%(msg,os.getpid(),os.getppid()))
    time.sleep(random.random()*2)
    t_stop = time.time()
    print(msg,"执行完毕,耗时%s秒"%(t_stop-t_start))



if __name__ == "__main__":
    print("++开始++")
    t0 = time.time()
    pool = Pool(3)
    for i in range(0, 10):
        pool.apply_async(worker, (i,))
    pool.close()#关闭进程池,关闭后不再接受新请求
    pool.join()#必须放在close语句后面
    t1 = time.time()
    print("++结束总耗时%s++" %(t1-t0))

进程中的消息队列Queue

from multiprocessing import Pool,Manager
import time,os,random

def write(q):
    for i in "ABC":
        print("正在往消息队列写入%s"%i)
        q.put(i)
        time.sleep(random.random())

def reader(q):
    while True:
        if not q.empty():
            i = q.get()
            print("从消息队列中读出%s"%i)
            time.sleep(random.random())
        else:
            break

if __name__ == "__main__":
    q = Manager().Queue()

    pool = Pool(3)

    pool.apply(write, (q,))
    pool.apply(reader, (q,))

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值