一、在python中的一些进程相关的模块和包:

  os.fork() (Linux)  subprocess  processing  Multiprocessing

二、进程间的通信方式:

  文件  管道(Pipes)  Socket  信号  信号量  共享内存

三、Multiprocessing.Process 说明

  1)作用:主要用于创建子进程

  2)语法

# 构造方法
help(multiprocessing.Process)
__init__(self, group=None, target=None, name=None, args=(), kwargs={})

# 参数说明
group:进程所属组,基本不用。
target:表示调用对象,一般为函数。
args:表示调用对象的位置参数元组。
name:进程别名。
kwargs:表示调用对象的字典。

#属性介绍
p.daemon:默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置

p.name:进程的名称

p.pid:进程的pid

# 方法介绍
p.start():# 启动进程,并调用该子进程中的p.run() 
p.run():# 进程启动时运行的方法,正是它去调用target指定的函数

p.terminate(): # 强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁
p.is_alive():# 如果p仍然运行,返回True

p.join([timeout]):# 主进程等待p(子进程)终止(强调:是主进程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间。

 

四、创建进程

  1)创建单进程

方式1:通过os.fork创建子进程(在Linux中执行)
import os 
print("process no:", os.getpid()) # 主进程的PID
pid = os.fork()  # 创建一个子进程,在此句中有两个进程(只是这个方法返回0结果表示创建子进程成功了,所以0并不能代表子进程pid)
                 # 主进程pid 和 子进程pid 

print(pid)  # 主进程pid  子进程pid
if pid == 0: 
    print("I am child process (%s) and my parent is %s "(os.getpid(),os.getppid())) # os.getppid()打印父进程ID
else:
    print("I (%s) just created a child process (%s). "(os.getpid(), pid))

print("*"*50) # 会被主进程打印一遍

# 结果是if 和 else都被执行了:子进程执行了if语句后面的内容,而主进程执行了else后面的内容



方式2:通过multiprocessing创建子进程

import multiprocessing  # 引入多进程的包

def do(n): # 任务函数
    name = multiprocessing.current_process().name # 获取进程的名字
    print(name, "starting")  # 打印进程名字
    print("worker", n)  # 打印worker的字符串信息
    return


if __name__ == "__main__":
    numList = []
    for i in range(5):
        p = multiprocessing.Process(name="test", target=do, args=(i,))
        numList.append(p)
        p.start()  # 启动执行新建进程的任务,进程会调用do函数来执行
        p.join()  # 等待当前进程执行完毕后,才会执行主进程后续代码
        print("process end.")
    print(numList)

注意:
在Windows上要想使用进程模块,就必须把有关进程的代码卸载当前.py文件的if __name ==‘__main__’的语句下面,才能正常的使用Windous下的进程模块,Unix/Linux下则不需要

  2)创建多进程

import multiprocessing
import urllib.request
import time


def func1(url) :
    response = urllib.request.urlopen(url)
    html = response.read()
    print(html[0:20])
    time.sleep(1)


def func2(url):
    response = urllib.request.urlopen(url)
    html = response.read()
    print(html[0:20])
    time.sleep(1)


if __name__ == '__main__':

    p1 =multiprocessing.Process(target=func1, args=("http://www.sogou.com",),name="gloryroad1")
    p2 =multiprocessing.Process(target=func2, args=("http://www.baidu.com",),name="gloryroad2")
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    time.sleep(1)
    print("done!")

# 同步进程池import multiprocessingimport time

def m1(x):
    time.sleep(0.01)
    return x.x + x.y


class a:  # 把参数封装进类里面,然后传递对象
    def __init__(self, x, y):
        self.x = x
        self.y = y


if __name__ == '__main__':

    pool = multiprocessing.Pool(multiprocessing.cpu_count())
    i_list = [a(i, i*10)for i in range(1000)]
    value = pool.map(m1, i_list)  # 使用多进程的方式执行任务,当有多个参数的时候可以使用对象
    print(value)

# 函数原型:map(func, iterable[, chunksize=None])

# Pool类中的map方法,与内置的map函数用法行为基本一致,它会使进程阻塞直到返回结果。

# 注意:虽然第二个参数是一个迭代器,但在实际使用中,必须在整个队列都就绪后,程序才会运行子进程。

# 异步进程池
from multiprocessing import Pool

def f(x):
    return x * x

if __name__ == '__main__':
    pool = Pool(processes = 4)  # 生成4个进程
    result = pool.apply_async(f, [10])  # 异步执行
    pool.close()
    pool.join() #调用join之前,先调用close函数,否则会出错。执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束
print(result.get(timeout=1))