一、在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))