ITPub博客

首页 > 应用开发 > IT综合 > 【Python】 多进程与多线程

【Python】 多进程与多线程

原创 IT综合 作者:小亮520cl 时间:2018-01-19 10:34:05 0 删除 编辑

1.多进程fork

  1. #!/usr/bin/env python
  2. #coding=utf8
  3.  
  4. from time import sleep
  5. import os
  6.  
  7. try:
  8.     pid = os.fork()
  9.     if pid == 0: ## fork一个子进程成功
  10.         sleep (30) ## 子进程代码
  11.     else:
  12.         parent_suite ## 父进程代码
  13. except OSError, e:
  14.     pass
  15.  
  16. print 'this is father ' ###父进程

运行
  1. [root@localhost /root ]# python tt2.py ####父进程立即结束
  2. this is father
  3. [root@localhost /root ]# ps -ef | grep -i python
  4. root 16837 1 0 16:02 pts/5 00:00:00 python tt2.py ###子进程在后台运行
  5. root 16853 13419 0 16:02 pts/5 00:00:00 grep -i python



2.多线程thread

http://www.cnblogs.com/fnng/p/3670789.html 

3 subprocess

Python中可以执行shell命令的相关模块和函数有:

  • os.system
  • os.spawn*
  • os.popen*          --废弃
  • popen2.*           --废弃
  • commands.*      --废弃,3.x中被移除

随着Python版本的更新,过多的模块引起代码的复杂与冗余,因此Python新引入了一个模块subprocess,将以上几个模块中的功能集中到它当中,以后我们只需import这一个即可。

subprocess的目的就是启动一个新的进程并且与之通信。

1. call与check_call

父进程等待子进程执行命令,返回子进程执行命令的状态码,如果出现错误,不进行报错

【这里说的返回执行命令的状态码的意思是:如果我们通过一个变量 res = subprocess.call(['dir',shell=True]) 获取的执行结果,我们能获取到的是子进程执行命令执行结果的状态码,即res=0/1 执行成功或者不成功,并不代表说看不到执行结果,在Python的console界面中我们是能够看到命令结果的,只是获取不到。想获取执行的返回结果,请看check_output。】

【不进行报错解释:如果我们执行的命令在执行时,操作系统不识别,系统会返回一个错误,如:abc命令不存在,这个结果会在console界面中显示出来,但是我们的Python解释器不会提示任何信息,如果想让Python解释器也进行报错,请看check_call】

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-

  3. import subprocess

  4. print "################## subprocess.call ###############"
  5. print u"call方法调用系统命令进行执行,如果出错不报错"
  6. subprocess.call(['dirt'],shell=True)
  7. print 'test1'
  8. subprocess.check_call(['dirt'],shell=True)
  9. print 'test2'
  10. ~
  [root@iZ2ze66bhrbxkc31nljgjnZ scripts]# python sub.py 
################## subprocess.call ###############
call方法调用系统命令进行执行,如果出错不报错
/bin/sh: dirt: command not found
test1                                       ----call 不进行报错,程序继续
/bin/sh: dirt: command not found
Traceback (most recent call last):
  File "sub.py", line 10, in
    subprocess.check_call(['dirt'],shell=True)
  File "/usr/lib64/python2.6/subprocess.py", line 505, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['dirt']' returned non-zero exit status 127   ---check_call报错,程序中断



Popen

  实际上,subprocess模块中只定义了一个类: Popen。上面的几个函数都是基于Popen()的封装(wrapper)。从Python2.4开始使用Popen来创建进程,用于连接到子进程的标准输入/输出/错误中去,还可以得到子进程的返回值。这些封装的目的在于让我们容易使用子进程。当我们想要更个性化我们的需求的时候,就要转向Popen类,该类生成的对象用来代表子进程。

构造函数如下:

subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)

与上面的封装不同,Popen对象创建后,主程序不会自动等待子进程完成。我们必须调用对象的wait()方法,父进程才会等待 (也就是阻塞block)。

1.不等待子进程
  1. #!/usr/bin/env python
  2. import subprocess

  3. child = subprocess.Popen(['ping','-c','4',''])
  4. print 'hello'

 [root@iZ2ze66bhrbxkc31nljgjnZ scripts]# python pop.py 
hello                                                                                                 ---父进程与子进程一起开始执行
[root@iZ2ze66bhrbxkc31nljgjnZ scripts]# PING (220.181.111.188) 56(84) bytes of data.
64 bytes from 220.181.111.188: icmp_seq=1 ttl=53 time=4.81 ms
64 bytes from 220.181.111.188: icmp_seq=2 ttl=53 time=4.75 ms
64 bytes from 220.181.111.188: icmp_seq=3 ttl=53 time=4.80 ms
64 bytes from 220.181.111.188: icmp_seq=4 ttl=53 time=4.88 ms

2.等待子进程
  1. #!/usr/bin/env python
  2. import subprocess

  3. child = subprocess.Popen(['ping','-c','4','www.baidu.com'])
  4. child.wait()
  5. print 'hello'


  6. [root@iZ2ze66bhrbxkc31nljgjnZ scripts]# python pop.py
  7. PING www.a.shifen.com (220.181.112.244) 56(84) bytes of data.
  8. 64 bytes from 220.181.112.244: icmp_seq=1 ttl=53 time=4.55 ms
  9. 64 bytes from 220.181.112.244: icmp_seq=2 ttl=53 time=4.60 ms
  10. 64 bytes from 220.181.112.244: icmp_seq=3 ttl=53 time=4.61 ms
  11. 64 bytes from 220.181.112.244: icmp_seq=4 ttl=53 time=4.58 ms

  12. --- www.a.shifen.com ping statistics ---
  13. 4 packets transmitted, 4 received, 0% packet loss, time 3006ms
  14. rtt min/avg/max/mdev = 4.559/4.591/4.615/0.022 ms
  15. hello
  

看出Python执行print操作是在child子进程操作完成以后才进行的。

此外,你还可以在父进程中对子进程进行其它操作,比如我们上面例子中的child对象:

child.poll() # 检查子进程状态 
child.kill() # 终止子进程 
child.send_signal() # 向子进程发送信号
child.terminate() # 终止子进程
ps: 子进程的PID存储在child.pid



子进程的标准输入、标准输出和标准错误如下属性分别表示:

child.stdin | child.stdout | child.stderr

我们还可以在Popen()建立子进程的时候改变标准输入、标准输出和标准错误,并可以利用subprocess.PIPE将多个子进程的输入和输出连接在一起,构成管道(pipe),如下2个例子:

例1 
#!/usr/bin/env python import subprocess

child = subprocess.Popen(['ls','-l'],stdout=subprocess.PIPE)    #将标准输出定向输出到subprocess.PIPE 
print child.stdout.read()                                           #使用 child.communicate()  也可

输出结果:

[root@localhost script]# python sub.py  
total 12-rw-r--r--. 1 root root  36 Jan 23 07:38 analyse.sh
-rw-r--r--. 1 root root 446 Jan 25 19:35 sub.py

例2 
#!/usr/bin/env python 
import subprocess
child1 = subprocess.Popen(['cat','/etc/passwd'],stdout=subprocess.PIPE)
child2 = subprocess.Popen(['grep','root'],stdin=child1.stdout,stdout=subprocess.PIPE) 
print child2.communicate()

输出结果为

('root:x:0:0:root:/root:/bin/bash\n, None)

		

subprocess.PIPE实际上为文本流提供一个缓存区。child1的stdout将文本输出到缓存区,随后child2的stdin从该PIPE中将文本读取走。child2的输出文本也被存放在PIPE中,直到communicate()方法从PIPE中读取出PIPE中的文本。
注意:communicate()是Popen对象的一个方法,该方法会阻塞父进程,直到子进程完成

子进程命令解释

  在上面的例子中我们创建子进程时,全部是调用Python进行解释,但Python并没有将所有命令全部解释,当Python不能进行解释时,就绪要调用系统来进行执行。


#!/usr/bin/env python 
import subprocess

subprocess.Popen(['ls','-l'])

subprocess.Popen(['ifconfig|grep 127.0.0.1'],shell=True)

结果

>>> subprocess.Popen(['ifconfig|grep 127.0.0.1'],shell=True)
>>>           inet addr:127.0.0.1  Mask:255.0.0.0


4 multiprocessing模块
  1. http://blog.csdn.net/myjiayan/article/details/46596161


参考:
Python的多线程threading不能并发
http://python.jobbole.com/81255/





来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29096438/viewspace-2150311/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
毕业以后专业任职数据库工程师职位,itpub一直作为自己的笔记记录的地方,blog写的不详细,草书笔记,仅供参考!

注册时间:2013-09-12

  • 博文量
    529
  • 访问量
    1129207