Python subprocess模块高级API详解:run、call与check系列方法

阿麦
阿麦
发布时间:2026-10-13 | 6人浏览过
原创

本文深入解析Python subprocess模块的高级API方法。重点介绍subprocess.run()及其capture_output、timeout、check等关键参数,对比分析subprocess.call()、check_call()和check_output()的使用场景与注意事项。同时涵盖getstatusoutput()等兼容旧版的方法,帮助开发者安全高效地调用外部进程。

subprocess.run()方法详解

subprocess.run()

该方法用于执行由args参数指定的命令,并等待其完成,最终返回一个CompletedProcess实例以包含执行结果。

其参数列表为(*popenargs, input=None, capture_output=False, timeout=None, check=False, **kwargs)。除了input、capture_output、timeout和check这四个特定参数外,其余参数均与Popen构造器的参数保持一致。

当capture_output设置为True时,系统会将stdout和stderr重定向至管道。此时若再显式传递stderr或stdout参数,程序将抛出异常,因为这两个输出流已被自动接管。

input参数作为标准输入传递给Popen的communicate()方法,其值必须为字符串(需指定encoding或errors参数,或设置text=True)或字节类型。若input不为None,则严禁与stdin参数同时使用,否则引发异常;此时Popen实例的stdin参数将被自动设置为subprocess.PIPE。

timeout参数直接传递给Popen的communicate()方法,用于限制命令执行的超时时间。

若check设置为True,当进程执行返回非0状态码时,将抛出CalledProcessError异常,以便开发者捕获处理错误。


# 源码

def run(*popenargs, input=None, capture_output=False, timeout=None, check=False, **kwargs):
  if input is not None:
    if 'stdin' in kwargs:
      raise ValueError('stdin and input arguments may not both be used.')
    kwargs['stdin'] = PIPE
  
  if capture_output:
    if ('stdout' in kwargs) or ('stderr' in kwargs):
      raise ValueError('stdout and stderr arguments may not be used '
               'with capture_output.')
    kwargs['stdout'] = PIPE
    kwargs['stderr'] = PIPE
  
  with Popen(*popenargs, **kwargs) as process:
    try:
      stdout, stderr = process.communicate(input, timeout=timeout)
    except TimeoutExpired:
      process.kill()
      stdout, stderr = process.communicate()
      raise TimeoutExpired(process.args, timeout, output=stdout,
                 stderr=stderr)
    except: # Including KeyboardInterrupt, communicate handled that.
      process.kill()
      # We don't call process.wait() as .__exit__ does that for us.
      raise
    retcode = process.poll()
    if check and retcode:
      raise CalledProcessError(retcode, process.args,
                   output=stdout, stderr=stderr)
  return CompletedProcess(process.args, retcode, stdout, stderr)

Python 3.5前的高级API方法

在Python 3.5版本之前,subprocess模块的高级API主要由call()、check_call()和check_output()这三个方法构成。

subprocess.call()的使用

subprocess.call()

该函数运行并等待args参数指定的指令完成,返回执行状态码,即Popen实例的returncode属性值。

其参数为(*popenargs, timeout=None, **kwargs),与Popen构造器参数基本相同,除timeout外的所有参数都会传递给Popen接口。

调用call()函数时,应避免使用stdout=PIPE或stderr=PIPE。如果子进程产生的输出量足以填满操作系统的管道缓冲区,子进程将因无法从管道读取数据而阻塞。


# 源码
def call(*popenargs, timeout=None, **kwargs):
  with Popen(*popenargs, **kwargs) as p:
    try:
      return p.wait(timeout=timeout)
    except:
      p.kill()
      p.wait()
      raise

subprocess.check_call()与错误处理

subprocess.check_call()

该函数运行并等待args参数指定的指令完成。若执行成功,返回0状态码;若失败,则抛出CalledProcessError异常。通过该异常的cmd和returncode属性,可以查看导致异常的指令及其状态码。

其参数为(*popenargs, **kwargs),所有参数均传递给call()函数处理。

其注意事项与call()函数相同,需特别注意管道缓冲区阻塞问题。


# 源码
def check_call(*popenargs, **kwargs):
  retcode = call(*popenargs, **kwargs)
  if retcode:
    cmd = kwargs.get("args")
    if cmd is None:
      cmd = popenargs[0]
    raise CalledProcessError(retcode, cmd)
  return 0

subprocess.check_output()与输出捕获

subprocess.check_output()

该函数运行并等待args参数指定的指令完成,返回标准输出内容(即CompletedProcess实例的stdout属性)。默认返回类型为byte字节,具体编码可能取决于执行的指令。若设置universal_newlines=True,则返回string类型的值。若执行状态码非0,将抛出CalledProcessError异常。

其参数为(*popenargs, timeout=None, **kwargs),所有参数均传递给run()函数,但不支持显式传递input=None以继承父进程的标准输入文件句柄。

若需在返回值中捕获标准错误,可设置stderr=subprocess.STDOUT;或者将标准错误重定向至管道(stderr=subprocess.PIPE),随后通过CalledProcessError异常的stderr属性进行访问。


# 源码

def check_output(*popenargs, timeout=None, **kwargs):
  if 'stdout' in kwargs:
    raise ValueError('stdout argument not allowed, it will be overridden.')

  if 'input' in kwargs and kwargs['input'] is None:
    # Explicitly passing input=None was previously equivalent to passing an
    # empty string. That is maintained here for backwards compatibility.
    kwargs['input'] = '' if kwargs.get('universal_newlines', False) else b''

  return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
        **kwargs).stdout

兼容旧版命令的方法

subprocess模块还保留了Python 2.x版本中commands模块的相关函数,以兼容旧代码。

getstatusoutput()与getoutput()

subprocess.getstatusoutput(cmd)

该函数实际调用check_output()方法,在shell中执行字符串类型的cmd指令,返回一个(exitcode, output)形式的元组。其中output部分包含stderr和stdout,是使用locale encoding解码后的字符串,并已去除结尾的换行符。


# 源码
try:
  data = check_output(cmd, shell=True, universal_newlines=True, stderr=STDOUT)
  exitcode = 0
except CalledProcessError as ex:
  data = ex.output
  exitcode = ex.returncode
if data[-1:] == '\n':
  data = data[:-1]
return exitcode, data

subprocess.getoutput(cmd)

该函数与getstatusoutput()类似,但结果仅返回output部分,不包含退出状态码。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表