Subprocess模块学习整理
1. subprocess模块的用途
subprocess模块用于主动创建新的进程,以执行用户预期的任务,例如在Windows的CMD执行执行一些指令,或在Linux下执行一些shell指令等。
该模块中的接口,可以替换一些旧版本的模块或函数:
os.system
os.spawn*
以下将通过对官方文档及subprocess模块源码做剖析式分析
2. class
subprocess模块共有5个类:
Popen(Object)
CompletedProcess(object)
SubprocessError(Exception)
–CalledProcessError(SubprocessError
)
–TimeoutExpired(SubprocessError
)
2.1 SubprocessError
subprocess模块的异常类基类,虚实现
2.2 CalledProcessError
继承自SubprocessError异常基类,当创建的进程执行返回值非0(执行出错)时,该异常将会抛出
2.3 TimeoutExpired
继承自SubprocessError异常基类,当创建的进程执行时间超出用户设置的超时时间时,该异常将会抛出
2.4 CompletedProcess
该类的实例时subprocess的run
方法的返回值,代表run方法创建的进程任务执行完毕。
该类只有一个实际作用的方法–check_returncode
class CompletedProcess(object):
"""A process that has finished running.
This is returned by run().
Attributes:
args: The list or str args passed to run().
returncode: The exit code of the process, negative for signals.
stdout: The standard output (None if not captured).
stderr: The standard error (None if not captured).
"""
def __init__(self, args, returncode, stdout=None, stderr=None):
self.args = args
self.returncode = returncode
self.stdout = stdout
self.stderr = stderr
def __repr__(self):
args = ['args={!r}'.format(self.args),
'returncode={!r}'.format(self.returncode)]
if self.stdout is not None:
args.append('stdout={!r}'.format(self.stdout))
if self.stderr is not None:
args.append('stderr={!r}'.format(self.stderr))
return "{}({})".format(type(self).__name__, ', '.join(args))
def check_returncode(self):
"""Raise CalledProcessError if the exit code is non-zero."""
if self.returncode:
raise CalledProcessError(self.returncode, self.args, self.stdout,
self.stderr)
2.5 Popen
该类时subprocess模块的核心类,一切与创建进程相关的操作,最终都是以先创建该类的实例为前提,再操作Popen的实例进行方法的调用。
subprocess模块中的很多类方法,都是对Popen类进行的封装,例如subprocess.run
,subprocess.call
等,
而另外还有一些方法,是对上述已封装的方法的进一步封装,例如subprocess.check_call
,subprocess.check_output
等。
Popen类实例化常用入参解析
def __init__(self, args, bufsize=-1, executable=None,
stdin=None, stdout=None, stderr=None,
preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS,
shell=False, cwd=None, env=None, universal_newlines=False,
startupinfo=None, creationflags=0,
restore_signals=True, start_new_session=False,
pass_fds=(), *, encoding=None, errors=None):
"""Create new Popen instance."""
member | description | usage |
---|---|---|
args | A string, or a sequence of program arguments | args = [“ls”, “-l”] |
args = “cmd” | ||
stdin | executed programs’ standard input | proc=Popen(args, stdin=PIPE, |
stdout=PIPE, stderr=PIPE) – 等待stdin | ||
out, err = proc.communicate(input=xxx) | ||
stdout/stderr | executed programs’ standard output error output | as above |
shell | If true, the command will be executed through the shell | |
cwd | Sets the current directory before the child is executed | |
universal_newlines | universal_newlines is true, file objects for stdin, stdout and stderr are opened in text mode using the specified encoding. Otherwise, file objects are opened in binary mode | |
encoding | Text mode encoding and error handling to use for file objects stdin, stdout and stderr | proc=Popen(args, shell=True, encoding=’gbk’, stdout=PIPE) |
同时,Popen支持通过with语句操作的context managers功能
with Popen(["ifconfig"], stdout=PIPE) as proc:
log.write(proc.stdout.read())
Popen的主要方法
func | description |
---|---|
Popen.poll() | Check if child process has terminated. Set and return returncode attribute. |
Popen.wait(timeout=None) | Wait for child process to terminate. Set and return returncode attribute. |
Note: This will deadlock when using stdout=PIPE or stderr=PIPE and the child process generates enough output to a pipe such that it blocks waiting for the OS pipe buffer to accept more data. Use Popen.communicate() when using pipes to avoid that. | |
Note: The function is implemented using a busy loop (non-blocking call and short sleeps). Use the asyncio module for an asynchronous wait: see asyncio.create_subprocess_exec. | |
Popen.communicate(input=None, timeout=None) | Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. |
Wait for process to terminate. The optional input argument should be data to be sent to the child process, or None, if no data should be sent to the child. If streams were opened in text mode, input must be a string. Otherwise, it must be bytes | |
communicate() returns a tuple (stdout_data, stderr_data) | |
The child process is not killed if the timeout expires, so in order to cleanup properly a well-behaved application should kill the child process and finish communication | |
Popen.kill() | Kills the child |
Popen.pid | The process ID of the child proces |
Popen.returncode | The child return code, set by poll() and wait() (and indirectly by communicate()). A None value indicates that the process hasn’t terminated yet. |