文章目录
进程
1. fork()
import os
pid = os.fork() # 系统遇到os.fork()会创建一个新的进程
if pid ==0: # 子进程值=0,父进程返回子进程的ID
print("哈哈哈")
else:
print("哈哈哈2")
2. getpid(),getppid()
getpid()
子进程getppid()
父进程
3. 多进程修改全局变量
多进程中,每个进程中所有数据(包括全局变量),都各自拥有一份,互不影响
4. 多次fork问题
- 类似于细胞分裂遇到
fork
分裂一次 - 父进程、子进程执行顺序没有规律,完全取决于操作系统的调度算法
5. 进程的创建-multiprocessing
multiprocessing模块提供了一个process
类来代表一个进程对象
from multiprocessing import Process
import os
# 子进程要执行代码
def run_proc(name):
print("子进程运行中,name=%s,pid=%d..." % (name, os.getpid()))
# 主进程
if __name__ == '__main__':
print("父进程%d" % os.getpid())
p = Process(target=run_proc, args=("test",))
p.start()
p.join()
- 创建子进程的时候,值需要传入一个 可执行函数 和 函数的参数,创建一个Process实例,用
start()
方法启动即可 join()
方法可以等待子进程结束后再继续往下运行,通常用于进程间同步
from multiprocessing import Process
import os
from time import sleep
def run_proc(name, age, **kwargs):
for i in range(10):
print("子进程运行中,name=%s, age=%d, pid=%d" % (name, age, os.getpid()))
print(kwargs)
sleep(0.5)
if __name__ == '__main__':
print("父进程%d" % os.getpid())
p = Process(target=run_proc, args=("test", 18), kwargs={"m":20, "a":18})
p.start()
sleep(1)
p.terminate()
p.join()
6. Process子类
还可以集成Process累,每次实例化这个类的时候,就等同于实例化一个进程对象
from multiprocessing import Process
import os
import time
class Process_Class(Process):
# 参数传递写在__init__方法中,另外因为重写了这个方法,Process类本身的属性也要实现,所以利用继承来完成
def __init__(self, interval, group=None, target=None, name=None, args=(), kwargs={}):
super().__init__(group=None, target=None, name=None, args=(), kwargs={})
self.interval = interval
# 方法实现写在run方法中
def run(self):
print("子进程(%s) 开始执行,父进程为(%s)" %(os.getpid(), os.getppid()))
t_start = time.time()
time.sleep(self.interval)
t_stop = time.time()
print("1(%s)执行结束,耗时%0.2f秒" % (os.getpid(), t_stop-t_start))
if __name__ == '__main__':
t_start = time.time()
print("当前程序进程(%s)" % os.getpid())
p1 = Process_Class(2)
p1.start()
p1.join() # 如果没有这句话的话主进程不会等待子进程,会一直往下走
t_stop = time.time()
print("2(%s)执行结束,耗时%0.2f" % (os.getpid(), t_stop-t_start))
7. 进程池
from multiprocessing import Pool
import time
import random
def worker(msg):
t_start = time.time()
time.sleep(random.random()*2)
t_stop = time.time()
print(msg, "执行完毕,耗时%0.2f" % (t_stop - t_start))
if __name__ == '__main__':
# 创建进程池
po = Pool(3)
for i in range(10):
# Pool.apply_async(要调用的目标,(传递给目标的参数元祖,))
po.apply_async(worker, (i,))
print("__start__")
po.close() # 关闭进程
po.join()
print("__end__")
- 堵塞方式必须等待上一个进程退出才能执行下一个进程
8. 进程之间通信- Queue
使用multiprocessing模块的Queue实现多进程之间的数据传递
from multiprocessing import Queue
q = Queue(3) # 初始化一个Queue对象,最多可以接受3条put信息
q.put("消息1")
q.put("消息2")
print(q.full())
q.put("消息3")
print(q.full())
try:
q.put("消息4", True, 2)
except:
print("消息列队已满,已有消息数量:%s" % q.qsize())
try:
q.put_nowait("消息4", True)
except:
print("消息列队已满,已有消息数量:%s" % q.qsize())
# 推荐方式,先判断消息列队是否已满,再写入
if not q.full():
q.put_nowait("消息4")
# 读取消息时,先判断消息队列是否为空,再读取
if not q.empty():
for i in range(q.qsize()):
print(q.get_nowait())
8.1 Process中的实例
在父进程中创建两个子进程,一个往Queue里写数据,另一个从Queue里读数据
from multiprocessing import Queue, Process
import os
import random
import time
def write(q): # 读和写放在同一个队列上通信
for value in ["a", "b", "c"]:
q.put(value)
time.sleep(random.random())
def read(q):
while True:
if not q.empty():
value = q.get(True)
print("get %s from queue." % value)
time.sleep(random.random())
else:
break
if __name__ == '__main__':
# 父进程创建Queue,并传递给各个子进程
q = Queue()
pw = Process(target=write, args=(q,))
pr = Process(target=read, args=(q,))
# 启动子进程pw,写入
pw.start()
pw.join() # 等待pw结束
# 启动子进程pr,读取
pr.start()
pr.join()
print("所有数据都写入并且读完")
8.2 进程池中的Queue
需要使用multiprocessing.Manger()
中的Queue
from multiprocessing import Manager, Pool
import os
def writer(q):
print("writer启动%s,父进程为%s" % (os.getpid(), os.getppid()))
for i in "donge":
q.put(i)
def reader(q):
print("reader启动%s,父进程%s" % (os.getpid(), os.getppid()))
for i in range(q.qsize()):
print("reader从Queue获取到信息:%s" % q.get(True))
if __name__ == '__main__':
print("主进程 %s start" % os.getpid())
q = Manager().Queue() # 使用 Manger中的Queue来初始化
po = Pool()
po.apply(writer, (q,))
po.apply(reader, (q,))
po.close()
po.join() # 让主线程等待子线程结束
print("主线程 %s end" % os.getpid())