设为首页 收藏本站
查看: 1022|回复: 0

[经验分享] python中的subprocess

[复制链接]

尚未签到

发表于 2018-8-6 09:39:37 | 显示全部楼层 |阅读模式
  python2.7 源码中的注释(由于能力有限,翻译的不太准确):
  这个模块允许您开启进程、连接输入、输出和错误的管道,并获取他们的返回代码。这个模块计划替代一些旧代码,如:
  os.system、os.spawn*、os.Popen、popen2.* 、commands.*
  关于subprocess模块可以用来取代这些模块和功能在下面可以找到
  这个模块定义了一个Popen的类:
  


  • class 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):
  

  参数为:
  args应该是一个字符串或序列的程序命令及参数。程序通常执行序列或字符串的第一项,但可以通过使用明确的参数进行设置。
  在UNIX上,shell = False(默认):在这种情况下,Popen类使用os.execvp()来执行程序的子进程。args应该通常是一个序列。字符串将被视为只有一个字符串的序列(程序执行)。

在UNIX上,shell= True:如果参数是一个字符串,它指定了通过shell执行命令字符串。如果参数是一个序列,第一项指定命令字符串,其他的将被视为附加的shell命令的参数。
在Windows:Popen类通过使用CreateProcess()执行这个子进程来对字符串操作。如果参数是一个序列,它将用list2cmdline方法将其转换成一个字符串。请注意,并不是所有的MS Windows应用程序解释命令行用相同的方法:list2cmdline是专为应用程序与MS C使用相同的规则。
bufsize,如果给定了,与内置行数open()的参数有相同意义:0意味着无缓冲的,1意味着线性缓冲,其他任何正值意味着使用的缓冲区(大约)大小。一个负bufsize意味着使用这个系统默认情况下,这通常意味着完全缓冲。默认值为bufsize是0(无缓冲的)。
stdin、stdout和stderr分别指定执行程序的标准输入,标准输出和标准错误。有效值是PIPE,现有的文件描述符(正整数),现有文件对象,None。PIPE创建一个新的子管道。None,没有重定向;子管道将会继承父管道的文件句柄。此外,标准错误可以用STDOUT来定义,表明应用程序应该从STDOUT捕获到相同的文件句柄的标准错误数据。
如果preexec_fn设置为一个可调用对象,该对象将在子进程执行之前调用。
如果close_fds 为True,所有的文件描述符除了0、1和2都会在子进程执行之前关闭。
如果shell是True,将通过shell执行指定的命令。
如果 cwd 不为None,子进程将在执行前切换到 cwd指定的目录
如果 env 不为空,为新进程定义环境变量
如果 universal_newlines 为 True, 则文件对象标准输出、标准错误输出以文本文件形式打开, 但是在unix系统中会以\n结束,windows中以\r\n结束。 在python程序中都是看作为\n 注意: 这种功能仅仅支持用通用换行符构建的python(默认)。同时文件对象标准输出、标准输入、标准错误的换行符属性,不会被communicate()模块所更新。
如果给定了startupinfo and creationflags参数, 将会转交给底层CreateProcess() 函数,他们可以指定诸如主窗体的外观、新进程的优先级之类的属性(仅支持windows)
这个模块也定义了一些简短的函数:
call(*popenargs, **kwargs):
    运行带参数的命令.  等待命令完成后返回返回码属性。
    这些参数相对于Popen构造函数是相同的。
    Example:
    retcode = call(["ls", "-l"])
check_call(*popenargs, **kwargs):
    运行带参数的命令.  等待命令完成.如果退出码是0则返回,如果是其他则抛出      
    CalledProcessError错误,该CalledProcessError 对象就会有返回返回码属性
    这些参数相对于Popen构造函数是相同的。
    Example:
    check_call(["ls", "-l"])
check_output(*popenargs, **kwargs):
    运行带参数的命令并且以字节字符串来返回。
    如果退出码是非0则会抛出CalledProcessError。
    CalledProcessError的对象将有返回代码在returncode属性和输出在output属性
    这些参数相对于Popen构造函数是相同的。
    Example:
    output = check_output(["ls", "-l", "/dev/null"])
异常处理:
==============
在新程序开始执行之前子进程抛出异常,之后父进程重新抛出异常。此外,异常对象会有一个额外称为'child_traceback'的属性,从子进程的角度上看,这是一个包含错误信息的字符串。
最常见的异常是OSError,比如:执行一个不存在的文件,应用程序会抛出OSError异常
如果Popen被无效的参数调用就会抛出‘ValueError’
如果check_call() and check_output()在被调用过程中返回一个非零的返回码则会抛出‘CalledProcessError’
安全
==============
和其他popen函数不同,它不会隐式的执行/bin/sh,这意味着所有的字符,包括shell元字符,可以安全地传递给子进程。
Popen 对象
=============
Popen类的实例有以下方法
poll()
    检查子进程是否终止,返回returncode属性
wait()
    等待子进程终止。返回returncode属性。
communicate(input=None)
    与进程相互作用: 发送数据到标准输入。从标准输出、标准错误读取数据, 直到到达文件尾。等待进程终止。可选的input参数应该是发送给子进程的字符串,或者如果没有要发送给子进程的数据那就用None
    communicate() 返回一个元组 (stdout, stderr).
    注意:读取的数据是保存在缓冲区中,因此,如果数据太大或没有限制则不要使用这个方法
下面的属性也是有效的:
=====================
stdin
    如果stdin参数是PIPE,这个属性是提供输入到子进程一个文件对象,否则为None
stdout
    如果stdout参数是PIPE , 这个属性是提供输出到子进程一个文件对象,否则为None
stderr
     如果stderr参数是PIPE , 这个属性是提供错误输出到子进程一个文件对象,否则为None
pid
    子进程的PID
returncode
    子进程的返回码。空值表示进程还没有结束,一个负值‘-N’表示子进程被信号N所结束(仅unix支持)
用subprocess模块取代旧函数:
====================================================
在本节中, "a ==> b" 意味着 b 可以替代 a.
注意: 如果没有找到执行程序,所有在本节中的函数都有可能以静默状态失败;这个模块会抛出OSError异常
在以下的例子中, 我们假设subprocess 模块是"from subprocess import *" 这样导入的:  


  • 替代 /bin/sh shell 的引号部分
  • ---------------------------------
  • output=`mycmd myarg`
  • ==>
  • output = Popen(["mycmd", "myarg"], stdout=PIPE).communicate()[0]


  • 替代 shell 的管道
  • -------------------------
  • output=`dmesg | grep hda`
  • ==>
  • p1 = Popen(["dmesg"], stdout=PIPE)
  • p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
  • output = p2.communicate()[0]


  • 替代 os.system()
  • ---------------------
  • sts = os.system("mycmd" + " myarg")
  • ==>
  • p = Popen("mycmd" + " myarg", shell=True)
  • pid, sts = os.waitpid(p.pid, 0)

  • 注意:

  • * 通过shell调用程序通常不是必须的

  • * 查看returncode attribute要比exitstatus容易些.

  • 一个更现实的例子:

  • try:
  •     retcode = call("mycmd" + " myarg", shell=True)
  •     if retcode < 0:
  •         print >>sys.stderr, &quot;Child was terminated by signal&quot;, -retcode
  •     else:
  •         print >>sys.stderr, &quot;Child returned&quot;, retcode
  • except OSError, e:
  •     print >>sys.stderr, &quot;Execution failed:&quot;, e


  • 替代 os.spawn*
  • -------------------
  • P_NOWAIT example:

  • pid = os.spawnlp(os.P_NOWAIT, &quot;/bin/mycmd&quot;, &quot;mycmd&quot;, &quot;myarg&quot;)
  • ==>
  • pid = Popen([&quot;/bin/mycmd&quot;, &quot;myarg&quot;]).pid


  • P_WAIT example:

  • retcode = os.spawnlp(os.P_WAIT, &quot;/bin/mycmd&quot;, &quot;mycmd&quot;, &quot;myarg&quot;)
  • ==>
  • retcode = call([&quot;/bin/mycmd&quot;, &quot;myarg&quot;])


  • Vector example:

  • os.spawnvp(os.P_NOWAIT, path, args)
  • ==>
  • Popen([path] + args[1:])


  • Environment example:

  • os.spawnlpe(os.P_NOWAIT, &quot;/bin/mycmd&quot;, &quot;mycmd&quot;, &quot;myarg&quot;, env)
  • ==>
  • Popen([&quot;/bin/mycmd&quot;, &quot;myarg&quot;], env={&quot;PATH&quot;: &quot;/usr/bin&quot;})


  • 替代 os.popen*
  • -------------------
  • pipe = os.popen(&quot;cmd&quot;, mode='r', bufsize)
  • ==>
  • pipe = Popen(&quot;cmd&quot;, shell=True, bufsize=bufsize, stdout=PIPE).stdout

  • pipe = os.popen(&quot;cmd&quot;, mode='w', bufsize)
  • ==>
  • pipe = Popen(&quot;cmd&quot;, shell=True, bufsize=bufsize, stdin=PIPE).stdin


  • (child_stdin, child_stdout) = os.popen2(&quot;cmd&quot;, mode, bufsize)
  • ==>
  • p = Popen(&quot;cmd&quot;, shell=True, bufsize=bufsize,
  •           stdin=PIPE, stdout=PIPE, close_fds=True)
  • (child_stdin, child_stdout) = (p.stdin, p.stdout)


  • (child_stdin,
  • child_stdout,
  • child_stderr) = os.popen3(&quot;cmd&quot;, mode, bufsize)
  • ==>
  • p = Popen(&quot;cmd&quot;, shell=True, bufsize=bufsize,
  •           stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
  • (child_stdin,
  • child_stdout,
  • child_stderr) = (p.stdin, p.stdout, p.stderr)


  • (child_stdin, child_stdout_and_stderr) = os.popen4(&quot;cmd&quot;, mode,
  •                                                    bufsize)
  • ==>
  • p = Popen(&quot;cmd&quot;, shell=True, bufsize=bufsize,
  •           stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
  • (child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout)

  • 在 Unix系统中, os.popen2, os.popen3 与 os.popen4 同样可以在没有shell介入的情况下直接传递给程序
  • 以序列形式执行命令行
  • 这种方法可以用下面的方法替换:

  • (child_stdin, child_stdout) = os.popen2([&quot;/bin/ls&quot;, &quot;-l&quot;], mode,
  •                                         bufsize)
  • ==>
  • p = Popen([&quot;/bin/ls&quot;, &quot;-l&quot;], bufsize=bufsize, stdin=PIPE, stdout=PIPE)
  • (child_stdin, child_stdout) = (p.stdin, p.stdout)

  • Return code handling translates as follows:

  • pipe = os.popen(&quot;cmd&quot;, 'w')
  • ...
  • rc = pipe.close()
  • if rc is not None and rc % 256:
  •     print &quot;There were some errors&quot;
  • ==>
  • process = Popen(&quot;cmd&quot;, 'w', shell=True, stdin=PIPE)
  • ...
  • process.stdin.close()
  • if process.wait() != 0:
  •     print &quot;There were some errors&quot;


  • 替代 popen2.*
  • ------------------
  • (child_stdout, child_stdin) = popen2.popen2(&quot;somestring&quot;, bufsize, mode)
  • ==>
  • p = Popen([&quot;somestring&quot;], shell=True, bufsize=bufsize
  •           stdin=PIPE, stdout=PIPE, close_fds=True)
  • (child_stdout, child_stdin) = (p.stdout, p.stdin)

  • 在 Unix系统中, popen2 也可以在没有shell介入的情况下直接传递给程序以序列形式执行命令行.
  • 这种方法可以用下面的方法替换:

  • (child_stdout, child_stdin) = popen2.popen2([&quot;mycmd&quot;, &quot;myarg&quot;], bufsize,
  •                                             mode)
  • ==>
  • p = Popen([&quot;mycmd&quot;, &quot;myarg&quot;], bufsize=bufsize,
  •           stdin=PIPE, stdout=PIPE, close_fds=True)
  • (child_stdout, child_stdin) = (p.stdout, p.stdin)

  • The popen2.Popen3 and popen2.Popen4 basically works as subprocess.Popen,
  • except that:

  • * subprocess.Popen raises an exception if the execution fails
  • * the capturestderr argument is replaced with the stderr argument.
  • * stdin=PIPE and stdout=PIPE must be specified.
  • * popen2 closes all filedescriptors by default, but you have to specify
  •   close_fds=True with subprocess.Popen.
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-547400-1-1.html 上篇帖子: python中paramiko的sftp_client类的注释 下篇帖子: Python 常用模块学习
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

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