Python3--Subprocess模組學習總結
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. |