python 多进程
- 多进程
multiprocessing
Pool
- 子进程
- 进程间通信
- 小结
-
多进程
- Unix/Linux系统中提供一个fork() 系统调用函数,可以fork 出子进程
- 调用一次返回两次,父进程(当前进程) + 子进程(复制)
- 在子进程中返回0, 父进程中返回子进程 ID
- 父进程可以fork多个子进程, 需要记下所有的子进程
- 子进程通过getppid() 拿到父进程的进程ID
-
import os # only works on Unix/Linux/Mac pid = os.fork() if pid == 0: print('当前为子进程id: %s , 父进程为:%s '%(os.getpid(), os.getppid())) else: print('当前进程id:%s,创建了子进程,id 为: %s'%(os.getpid(), pid) )
-
multiprocessing
multiprocessing
模块是跨平台版本的多进程模块( windows上无法使用fork)-
from multiprocessing import Process import os # 子进程要执行的代码 def run_proc(name): print("子进程%s(%s))运行"%(name, os.getpid())) if __name__ == '__main__': print('当前进程%s' %s os.getpid()) p = Process(target=run_proc, args('test,')) print('子进程即将启动') p.start() # 启动进程,较fork()更简单 p.join() # 等待子进程结束, 通常用于进程就同步 print('子进程结束')
-
Pool
- 启动大量子进程, 可以使用进程池的方法批量创建
-
from multiprocessing import Process import os, time, random def long_time_task(name): print('运行任务%s(%s)...'%(name, os.getpid())) start = time.time() time.sleep(random.random() * 3) end = time.time() print('任务%s 耗时 %0.2f 秒'%(name,(end-start) ) if __name__ == '__main__': print('当前进程(%s)'% os.getpid()) p = Pool(4) # 设置同时运行4个进程的限制, 默认大小CPU的核数 for i in range(5): p.apply_async(long_time_task, args=(i,)) print('等待所有子进程运行结束') p.close() # 必须先调用, 调用后不能够在添加进程 p.join() # 等待所有子进程执行结束 print('所有子进程运行结束')
-
子进程
subprocess
模块可以方便地启动一个子进程,然后控制子进程输入输出- 实现命令
nslookup www.python.org
-
import subprocess print('$ nslookup www.python.org') r = subprocess.call(['nslookup', 'www.python.org']) print('退出码', r)
- 实现命令
nslookup
-
import subprocess print('$ nslookup') p = subprocess.Popen(['nslookup'], stdin=subprocess.PIPE, stdout=subprocess.PIPE) output, err = p.communicate(b'set q=mx\npython.org\nexit\n') print(output.decode('utf-8')) print('推出码', p.returncode) # 执行命令 nslookup 后, 手动输入 'set q=mx\npython.org\nexit\n'
-
进程间的通信
multiprocessing
模块提供了Queue
、Pipes
等多种方式来交换数据Queue
读取数据-
from multiprocessing import Process, Queue import os,time, random def write(q): print('用于写入数据的进程:%s' % os.getpid()) for value in ['A', 'B', 'C']: print('把%s放入队列'%s value) q.put(value) time.sleep(random.random()) def read(q): print('用于读取数据的进程:%s'%s os.getpid()) while True: value = q.get(True) print('队列中获取值: %s' %s value) def __name__ == '__main__': q =Quee() pw = Process(target=write, args=(q,)) pd = Process(target=write,args=(q,)) pw.start() # 启动进程, 写入 pr.start() # 启动进程, 读取 pw.join() # 等待写入结束 pr.terminate() # while True 为死循环, 强行终止
-
小结
Unix/Linux
系统, 可以使用fork()
实现多进程- 实现跨平台的多进程,可以使用
multiproessing
模块multiprocessing
在win系统, 需要模拟fork
的效果。- 父进程所有
Python
对象都必须通过pickle
序列化在传入子进程
- 进程间通信是通过
Queue
、Pipes
等实现的