51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 1531|回复: 2
打印 上一主题 下一主题

python多进程编写

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2018-2-26 15:28:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
第一种:使用fork创建多进程(windows没有fork调用)
     要让Python程序实现多进程(multiprocessing),我们先了解操作系统的相关知识。Unix/Linux操
作系统提供了一个fork()系统调用,它非常特殊。普通的函数调用,调用一次,返回一次,但是fork()
调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然
后,分别在父进程和子进程内返回。子进程永远返回0,而父进程返回子进程的ID。这样做的理由是,
一个父进程可以fork出很多子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用getppid
()就可以拿到父进程的ID。
      Python的os模块封装了常见的系统调用,其中就包括fork,可以在Python程序中轻松创建子进程:
  1. import os  
  2.   
  3. print ('Process (%s) start...' % os.getpid())  
  4. pid = os.fork()  
  5. if pid==0:  
  6.     print ('I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid()))  
  7. else:  
  8.     print ('I (%s) just created a child process (%s).' % (os.getpid(), pid))  
复制代码
运行结果:
  1. Process (49290) start...  
  2. I (49290) just created a child process (49305).父进程  
  3. I am child process (49305) and my parent is 49290.子进程  
复制代码
第二种:使用multiprocessing创建多进程(跨平台版本)
    multiprocessing模块提供了一个Process类来代表一个进程对象,其中参数target表示子进程执行
的函数,args表示子进程函数的参数。下面的例子演示了启动一个子进程并等待其结束:
  1. from multiprocessing import Process  
  2. import os  
  3.   
  4. # 子进程要执行的代码  
  5. def run_proc(name):  
  6.     print('Run child process %s (%s)...' % (name, os.getpid()))  
  7.   
  8. if __name__=='__main__':  
  9.     print('Parent process %s.' % os.getpid())  
  10.     p = Process(target=run_proc, args=('test',))  
  11.     print ('Process will start.')  
  12.     p.start()  
  13.     p.join()  
  14.     print ('Process end.')  
  15. 运行结果:
  16. [python] view plain copy
  17. Parent process 49290.  
  18. Process will start.  
  19. Run child process test (49702)...  
  20. Process end.  
复制代码
代码解读:  
       创建子进程时,只需要传入一个执行函数和函数的参数,创建一个Process实例,用start()方法
启动,这样创建进程比fork()还要简单。join()方法可以等待子进程结束后再继续往下运行,通常用于
进程间的同步。
第三种:使用Pool启动大量的子进程(跨平台版本)
  1. from multiprocessing import Pool  
  2. import os, time, random  
  3.   
  4. def long_time_task(name):  
  5.     print ('Run task %s (%s)...' % (name, os.getpid()))  
  6.     start = time.time()  
  7.     time.sleep(random.random() * 3)  
  8.     end = time.time()  
  9.     print ('Task %s runs %0.2f seconds.' % (name, (end - start)))  
  10.   
  11. if __name__=='__main__':  
  12.     print ('Parent process %s.' % os.getpid())  
  13.     p = Pool()  
  14.     for i in range(5):  
  15.         p.apply_async(long_time_task, args=(i,))  
  16.     print ('Waiting for all subprocesses done...')  
  17.     p.close()  
  18.     p.join()  
  19.     print ('All subprocesses done.')  
  20. 结果如下:
  21. [python] view plain copy
  22. Parent process 49885.  
  23. Run task 2 (49970)...  
  24. Run task 0 (49968)...  
  25. Run task 1 (49969)...  
  26. Run task 3 (49971)...  
  27. Run task 4 (49972)...  
  28. Waiting for all subprocesses done...  
  29. Task 3 runs 1.08 seconds.  
  30. Task 4 runs 1.25 seconds.  
  31. Task 1 runs 1.32 seconds.  
  32. Task 2 runs 1.50 seconds.  
  33. Task 0 runs 2.19 seconds.  
  34. All subprocesses done.  
复制代码
代码解读:
     对Pool对象调用join()方法会等待所有子进程执行完毕,调用join()之前必须先调用close(),调用
close()之后就不能继续添加新的Process了。请注意输出的结果,task0,1,2,3是立刻执行的,而
task4要等待前面某个task完成后才执行,这是因为Pool的默认大小在我的电脑上是4,因此,最多
同时执行4个进程。这是Pool有意设计的限制,并不是操作系统的限制。如果改成:p = Pool(5)就
可以同时跑5个进程。由于Pool的默认大小是CPU的核数,如果你不幸拥有8核CPU,你要提交至少
9个子进程才能看到上面的等待效果。
第四种:进程间通信
     Process之间肯定是需要通信的,操作系统提供了很多机制来实现进程间的通信。Python的
multiprocessing模块包装了底层的机制,提供了Queue、Pipes等多种方式来交换数据。
我们以Queue为例,在父进程中创建两个子进程,一个往Queue里写数据,一个从Queue里读数据:
  1. from multiprocessing import Process, Queue  
  2. import os, time, random  
  3.   
  4. # 写数据进程执行的代码:  
  5. def write(q):  
  6.     for value in ['A', 'B', 'C']:  
  7.         print ('Put %s to queue...' % value)  
  8.         q.put(value)  
  9.         time.sleep(random.random())  
  10.   
  11. # 读数据进程执行的代码:  
  12. def read(q):  
  13.     while True:  
  14.         value = q.get(True)  
  15.         print ('Get %s from queue.' % value)  
  16.   
  17. if __name__=='__main__':  
  18.     # 父进程创建Queue,并传给各个子进程:  
  19.     q = Queue()  
  20.     pw = Process(target=write, args=(q,))  
  21.     pr = Process(target=read, args=(q,))  
  22.     # 启动子进程pw,写入:  
  23.     pw.start()  
  24.     # 启动子进程pr,读取:  
  25.     pr.start()  
  26.     # 等待pw结束:  
  27.     pw.join()  
  28.     # pr进程里是死循环,无法等待其结束,只能强行终止:  
  29.     pr.terminate()  
  30. 运行结果:
  31. [python] view plain copy
  32. Put A to queue...  
  33. Get A from queue.  
  34. Put B to queue...  
  35. Get B from queue.  
  36. Put C to queue...  
  37. Get C from queue.  
复制代码


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏
回复

使用道具 举报

本版积分规则

关闭

站长推荐上一条 /1 下一条

小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

GMT+8, 2024-11-22 08:14 , Processed in 0.063737 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2024 Comsenz Inc.

快速回复 返回顶部 返回列表