python中的subprocess

发布时间:2019-09-19 08:04:45编辑:auto阅读(1563)

     python2.7 源码中的注释(由于能力有限,翻译的不太准确):

    这个模块允许您开启进程、连接输入、输出和错误的管道,并获取他们的返回代码。这个模块计划替代一些旧代码,如:

    os.system、os.spawn*、os.Popen、popen2.* 、commands.*

    关于subprocess模块可以用来取代这些模块和功能在下面可以找到

    这个模块定义了一个Popen的类:

    1. class Popen(args, bufsize=0, executable=None
    2.             stdin=None, stdout=None, stderr=None
    3.             preexec_fn=None, close_fds=False, shell=False
    4.             cwd=None, env=None, universal_newlines=False
    5.             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 *" 这样导入的:
     
     
    1. 替代 /bin/sh shell 的引号部分 
    2. --------------------------------- 
    3. output=`mycmd myarg` 
    4. ==> 
    5. output = Popen(["mycmd""myarg"], stdout=PIPE).communicate()[0
    6.  
    7.  
    8. 替代 shell 的管道
    9. ------------------------- 
    10. output=`dmesg | grep hda` 
    11. ==> 
    12. p1 = Popen(["dmesg"], stdout=PIPE) 
    13. p2 = Popen(["grep""hda"], stdin=p1.stdout, stdout=PIPE) 
    14. output = p2.communicate()[0
    15.  
    16.  
    17. 替代 os.system() 
    18. --------------------- 
    19. sts = os.system("mycmd" + " myarg"
    20. ==> 
    21. p = Popen("mycmd" + " myarg", shell=True
    22. pid, sts = os.waitpid(p.pid, 0
    23.  
    24. 注意: 
    25.  
    26. * 通过shell调用程序通常不是必须的 
    27.  
    28. * 查看returncode attribute要比exitstatus容易些. 
    29.  
    30. 一个更现实的例子: 
    31.  
    32. try
    33.     retcode = call("mycmd" + " myarg", shell=True
    34.     if retcode < 0
    35.         print >>sys.stderr, "Child was terminated by signal", -retcode 
    36.     else
    37.         print >>sys.stderr, "Child returned", retcode 
    38. except OSError, e: 
    39.     print >>sys.stderr, "Execution failed:", e 
    40.  
    41.  
    42. 替代 os.spawn* 
    43. ------------------- 
    44. P_NOWAIT example: 
    45.  
    46. pid = os.spawnlp(os.P_NOWAIT, "/bin/mycmd""mycmd""myarg"
    47. ==> 
    48. pid = Popen(["/bin/mycmd""myarg"]).pid 
    49.  
    50.  
    51. P_WAIT example: 
    52.  
    53. retcode = os.spawnlp(os.P_WAIT, "/bin/mycmd""mycmd""myarg"
    54. ==> 
    55. retcode = call(["/bin/mycmd""myarg"]) 
    56.  
    57.  
    58. Vector example: 
    59.  
    60. os.spawnvp(os.P_NOWAIT, path, args) 
    61. ==> 
    62. Popen([path] + args[1:]) 
    63.  
    64.  
    65. Environment example: 
    66.  
    67. os.spawnlpe(os.P_NOWAIT, "/bin/mycmd""mycmd""myarg", env) 
    68. ==> 
    69. Popen(["/bin/mycmd""myarg"], env={"PATH""/usr/bin"}) 
    70.  
    71.  
    72. 替代 os.popen* 
    73. ------------------- 
    74. pipe = os.popen("cmd", mode='r', bufsize) 
    75. ==> 
    76. pipe = Popen("cmd", shell=True, bufsize=bufsize, stdout=PIPE).stdout 
    77.  
    78. pipe = os.popen("cmd", mode='w', bufsize) 
    79. ==> 
    80. pipe = Popen("cmd", shell=True, bufsize=bufsize, stdin=PIPE).stdin 
    81.  
    82.  
    83. (child_stdin, child_stdout) = os.popen2("cmd", mode, bufsize) 
    84. ==> 
    85. p = Popen("cmd", shell=True, bufsize=bufsize, 
    86.           stdin=PIPE, stdout=PIPE, close_fds=True
    87. (child_stdin, child_stdout) = (p.stdin, p.stdout) 
    88.  
    89.  
    90. (child_stdin, 
    91.  child_stdout, 
    92.  child_stderr) = os.popen3("cmd", mode, bufsize) 
    93. ==> 
    94. p = Popen("cmd", shell=True, bufsize=bufsize, 
    95.           stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True
    96. (child_stdin, 
    97.  child_stdout, 
    98.  child_stderr) = (p.stdin, p.stdout, p.stderr) 
    99.  
    100.  
    101. (child_stdin, child_stdout_and_stderr) = os.popen4("cmd", mode, 
    102.                                                    bufsize) 
    103. ==> 
    104. p = Popen("cmd", shell=True, bufsize=bufsize, 
    105.           stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True
    106. (child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout) 
    107.  
    108. 在 Unix系统中, os.popen2, os.popen3  os.popen4 同样可以在没有shell介入的情况下直接传递给程序
    109. 以序列形式执行命令行  
    110. 这种方法可以用下面的方法替换
    111.  
    112. (child_stdin, child_stdout) = os.popen2(["/bin/ls""-l"], mode, 
    113.                                         bufsize) 
    114. ==> 
    115. p = Popen(["/bin/ls""-l"], bufsize=bufsize, stdin=PIPE, stdout=PIPE) 
    116. (child_stdin, child_stdout) = (p.stdin, p.stdout) 
    117.  
    118. Return code handling translates as follows: 
    119.  
    120. pipe = os.popen("cmd"'w'
    121. ... 
    122. rc = pipe.close() 
    123. if rc is not None and rc % 256
    124.     print "There were some errors" 
    125. ==> 
    126. process = Popen("cmd"'w', shell=True, stdin=PIPE) 
    127. ... 
    128. process.stdin.close() 
    129. if process.wait() != 0
    130.     print "There were some errors" 
    131.  
    132.  
    133. 替代 popen2.* 
    134. ------------------ 
    135. (child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode) 
    136. ==> 
    137. p = Popen(["somestring"], shell=True, bufsize=bufsize 
    138.           stdin=PIPE, stdout=PIPE, close_fds=True
    139. (child_stdout, child_stdin) = (p.stdout, p.stdin) 
    140.  
    141. 在 Unix系统中, popen2 也可以在没有shell介入的情况下直接传递给程序以序列形式执行命令行.  
    142. 这种方法可以用下面的方法替换: 
    143.  
    144. (child_stdout, child_stdin) = popen2.popen2(["mycmd""myarg"], bufsize, 
    145.                                             mode) 
    146. ==> 
    147. p = Popen(["mycmd""myarg"], bufsize=bufsize, 
    148.           stdin=PIPE, stdout=PIPE, close_fds=True
    149. (child_stdout, child_stdin) = (p.stdout, p.stdin) 
    150.  
    151. The popen2.Popen3 and popen2.Popen4 basically works as subprocess.Popen, 
    152. except that: 
    153.  
    154. * subprocess.Popen raises an exception if the execution fails 
    155. * the capturestderr argument is replaced with the stderr argument. 
    156. * stdin=PIPE and stdout=PIPE must be specified. 
    157. * popen2 closes all filedescriptors by default, but you have to specify 
    158.   close_fds=True with subprocess.Popen. 
     

     

关键字