python-进程二(创建进程)
一、在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!")
3)创建进程池(进程池分两种:一种是同步进程池,一种是异步进程池)# 同步进程池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))