subprocess

*****本文参考了Vamei大神的http://www.cnblogs.com/vamei/archive/2012/09/23/2698014.html  

 运用subprocess包可以在运行python的进程下进一步开启一个子进程,创建子进程要注意

    1. 父进程是否暂停

    2.创建出的子进程返回了什么

    3.执行出错,即返回的code不是0的时候应该如何处理

  subprocess包提供了三个开启子进程的方法,subprocess.call() , subprocess.check_call() , subprocess.check_output(),给三者传递命令字符串作为参数。可以用(['ping','www.baidu.com','-c','3'])这种列表的形式,同时也可以是("ping www.baidu.com -c 3") 这种形式。在开启子进程的时候,可以加上shell=True的参数来让python开启一个shell,通过shell来解释获得的命令。一般在windows下运行的程序最好都把shell=True加上,这样才能顺利地执行dos命令,但是linux下似乎不加也没啥关系。因为linux下未指明用shell执行的话会调用/bin/sh来执行,问题不大,但是dos下系统不会默认用cmd.exe来执行命令,所以要加上shell=True。

  subprocess.call ; subprocess.check_call ; subprocess.check_output  这三者的区别在于,返回的值分别是,子进程的执行返回码;若返回码是0则返回0,否则出错的话raise起CalledProcessError,可以用except处理之;若返回码是0则返回子进程向stdout输出的结果,否则也raise起CalledProcessError。另外,这三个方法都是让父进程挂起等待的,在子进程结束之前,父进程不会继续往下运行。

  另外从本质上讲,上述三个方法都是对subprocess.Popen方法的一个包装,Popen开启的子进程是不会让父进程等待其完成的,除非调用了wait()方法:

child = subprocess.Popen("...",shell=True)
print "Hello"
"""
很可能hello在子进程的输出之前就被打印出来了,因为父进程不等child子进程运行完
"""child = subprocess.Popen("...",shell=True)
child.wait()
print "Hello"
"""
这就不一样,父进程一定会等子进程运行完,给出完整的结果之后再继续往下执行。相当于wait函数挂起了父进程。
"""

  此外,上面代码里的child这个对象还有其他的一些方法:

    child.poll()  返回子进程运行状态,主要是两种结果,None代表尚未运行完,而一个返回码则代表已经运行完成并且是成功或失败了

    child.kill()  强行终止子进程

    child.send_signal(...)  向子进程发送一个信号(具体信号是以什么方式表示不清楚,还待研究)

    child.terminate()  终止子进程

    child.pid  子进程的pid

    child.returncode  子进程的返回码

    child.stdin/stdout/stderr    子进程的标准输入流,标准输出和标准错误输出,都是类文件对象

■  文本流控制

  每个子进程对象都有stdin/stdout/stderr三个对象,而在Popen开启子进程的时候,可以设置这三个对象。比如

child1 = subprocess.Popen("cmd1",shell=True, stdout=subprocess.PIPE)
'''
child1的stdout被设置成管道,可以把它理解成一个第三方托管机构,
因为不设置的话child1的stdout的内容就直接被打印到父进程的stdout里了,
设置成管道之后内容被导入了PIPEという名の第三方托管机构里
'''
child2 = subprocess.Popen("cmd2",shell=True,stdin=child1.stdout,stdout=subprocess.PIPE)
'''
把child2的stdin设置成了child1的stdout,也就是之前那个第三方机构,这么一来就实现了两个子进程之间的数据通信了。而把child2的stdout也设置成第三方,是因为不想让child2的输出就直接这么输出到父进程的stdout里,而要对它做一些处理
'''
stdout,tmp = child2.communicate()
'''
因为child2的输出不用再转给个child3去处理,就用communicate方法把第三方机构那里的数据取出来放进一个变量里。注意,这里的stdout已经是个str对象了,communicate出来的都是字符串了communicate方法自带wait功能,会让父进程挂起等待所有子进程结束communicate会返回一个元组,但是像在这个例子中没有设置stderr=PIPE,所以元组中的第二项原本属于stderr的值的地方的tmp的值是None,如果设置了其为PIPE,由于没有错误信息tmp是""。这点是有区别的。
'''
print "We have result:\n%s"%(stdout)    #代表了把stdout做一些处理后再输出

■  Popen方法

  Popen就是开启一个新的子进程,常用的几个参数正如上面所提的cmd,shell,stdin,stdout,stderr来指定开启的子进程的一些属性。

  除此之外还有以下的参数:

    close_fds  默认为False,设置为True的情况下会在子进程执行之前关闭所有除了0,1,2之外的所有文件都关闭(虽然不知道有什么意义)

    cwd  默认None,可以为子进程设置工作目录

  盗了张图(http://www.cnblogs.com/zhoug2020/p/5079407.html)

  

  实际上,我一般都是这么干的:

import subprocessp = subprocess.Popen("CMD",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
stdout,stderr = p.communicate()
if stderr != "":print "ERROR:"+stderr
else:print "RESULT:"+stdout

*这篇文章(http://www.tuicool.com/articles/bUNJ7v)提供了一个解决大量并发开启子进程时出bug的方案,同时也给了一个如何为一个子进程设置超时的方法,值得看一下:

def timeout_command(command, timeout):start = datetime.datetime.now()process = subprocess.Popen(command, bufsize=10000, stdout=subprocess.PIPE, close_fds=True)'''这个循环就是为子进程设置了超时功能,感觉还挺巧妙的。。'''while process.poll() is None:time.sleep(0.1)now = datetime.datetime.now()if (now - start).seconds> timeout:try:process.terminate()except Exception,e:return Nonereturn Noneout = process.communicate()[0]if process.stdin:process.stdin.close()if process.stdout:process.stdout.close()if process.stderr:process.stderr.close()try:process.kill()except OSError:passreturn out

■  关于实时获取子进程输出的方法

  之前用过的所有subprocess.Popen方法吧,打开的子进程都比较短小,其命令基本上都可以在一秒内完成。所以在communicate的时候都没有显示出什么不妥的地方。但是碰到一些比较大,运行时间比较长的命令时,communicate就显得有些不太好了,因为到命令运行完成或者缓冲区满为止,子进程对象是不会向程序返回输出内容的。此时就需要变通一点不要使用communicate了。

  一个解决的办法是这样的:

import subprocess
import sysp = subprocess.Popen('cmd',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)while p.poll() is None:    #当子进程没有完成之前char = p.stdout.read(1)sys.stdout.write(char)stdout,stderr = p.communicate()
sys.stdout.write(stdout)

  观察这段程序,可以看到,当子进程没有结束之前,循环将不断地从子进程的stdout中读取一个字符的数据然后写到父进程的stdout中。如果子进程较长时间没有明文进入stdout的话也可以在循环中加上一个time.sleep来控制循环频率。下面再加上communicate是为了保证信息输出的完整性。因为当子进程结束之后,有可能stdout还没有读取光,如果不加communicate的话那么还剩余在stdout中的信息就丢失了。如果子进程在stderr中有输出那么也可以放在communicate后面判断。另外也可以在建立p对象的时候把stderr参宿设置为subprocess.STDOUT来把子进程的stderr输出重定向到stdout中。

  *测试的时候,把一个每sleep1秒就向stdout写入一些信息的脚本当做子进程。但是发现以上方法并不奏效。想了下之后,记起来python在写文件的时候是会有缓冲区这个设定的。也就是说,子进程代码中的write被调用后stdout并不马上把信息输出到stdout中。解决办法就是用file对象(这里是sys.stdout)调用flush()方法来清空缓存并写入文件。

转载于:https://www.cnblogs.com/franknihao/p/6537159.html

【Python】 子进程创建与使用subprocess相关推荐

  1. python子进程模块subprocess

    2019独角兽企业重金招聘Python工程师标准>>> python子进程模块subprocess 目录 一.subprocess 模块简介 1.1. 使用 subprocess模块 ...

  2. linux shell 子进程结束,关于linux:如何终止以shell = True启动的python子进程

    我正在使用以下命令启动子流程: p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) 但是,当我尝试杀死使用: p.termina ...

  3. python子进程异常结束_Python子进程

    python子进程异常结束 Python subprocess module provides easy functions that allow us to spawn a new process ...

  4. Python系列 49 内置模块:subprocess

    subprocess简介 subprocess模块最早在Python2.4中引入,它会生成一个子进程,该子进程可以执行shell命令,并且会监听系统的标准输入管道.标准输出管道.标准错误管道,在命令执 ...

  5. 用Python从零开始创建区块链

    链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载. 前言 如果你还没有听说过 3 点钟区块链群,说明你还不是链圈的人:如果你还没有加入 3 点钟区块链群,说明你还不是链圈的 ...

  6. python中创建列表[]和list()哪个效率快?为什么快?快多少呢?

    python中创建列表的两种方式: # 方法一:使用成对的方括号语法 list_a = []# 方法二:使用内置的 list() list_b = list() 1. [] 是 list() 的三-四 ...

  7. 如何在 Python 中创建一个简单的神经网络

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 引言 在过去的几十年里,机器学习对世界产生了巨大的影响,而且它的普 ...

  8. python软件怎么用-Python如何创建应用程序

    Python如何创建应用程序 1.使用wxPython之前,先来了解两个基础对象:应用程序对象和顶级窗口. 应用程序对象管理主事件循环,主事件循环是wxPython程序的动力,如果没有应用程序对象,w ...

  9. python简单代码演示效果-演示python如何创建和使用一个简单的元类的代码

    在做工程闲暇时间,将做工程过程比较重要的一些内容备份一下,如下内容段是关于演示python如何创建和使用一个简单的元类的内容,应该能对小伙伴们也有用途. #!/usr/bin/env python # ...

最新文章

  1. NFS基本配置与NFS客户端自动挂载
  2. python基础教程:函数装饰器详解
  3. elasticsearch 6.2.3 从零开始配置
  4. SQLAlchemy Script
  5. 混合app用百分比还是rem_[笔记]em, rem最佳实践
  6. java下载配置步骤_Java环境构建-JDK下载,安装和配置步骤
  7. 使用Python写的第一个网络爬虫程序
  8. 三层交换原理及实验操作
  9. 门锁了开不了_送智能门锁丨选购时没有注意这些,着火时智能门锁可能会打不开?...
  10. Vim快捷键-键位图
  11. 对Gamma校正的理解
  12. 计算机中重命名的英文单词,重命名是什么意思
  13. C#调用Outlook发送邮件
  14. 进不去jetbrain官网怎么办
  15. 用c语言写图书馆程序,用c语言写图书馆管理系统
  16. 少走弯路的3个忠告:产品经理不是来改变世界的
  17. java.lang.AbstractMethodError: Method com/mchange/v2/c3p0/impl/NewProxyPreparedStatement.isClosed()Z
  18. wp手机开发之获取汉字拼音的首字母
  19. 软考是什么?怎么准备----软考相关资讯
  20. 26.java-BufferedWriter写文件

热门文章

  1. 演示教学法在计算机基础课程中的应用,演示教学法在《计算机基础》课程中的应用...
  2. scrt如何切换成英文版_英文版SecureCRT显示乱码解决
  3. var模型的matlab实现_Eviews中VAR模型的操作、脉冲响应分析和方差分解的实现
  4. mysqld进程 ut_delay 占用率过高
  5. C++网络编程快速入门(三):阻塞与非阻塞式调用网络通信函数
  6. 形态学操作——击中击不中变换
  7. scala char_Scala中的Char数据类型
  8. c语言条件语句示例_PHP中的条件语句和示例
  9. Python---实验八
  10. linux文件操作相关函数