文章目录
- Windows 调用外部程序
- OS 模块
- subprocess 模块
- Popen--最基本的类
- Popen 的常用方法
- Popen 的属性
- 常量
- 基于 Popen 的其他方法
- subprocess.call(\*popenargs, timeout=None, \*\*kwargs)
- subprocess.check_call(\*popenargs, \*\*kwargs)
- CompletedProcess 类
- subprocess.run(\*popenargs, input=None, capture_output=False, timeout=None, check=False, \*\*kwargs):
- subprocess.check_output(\*popenargs, timeout=None, \*\*kwargs)
- 疑问
- subprocess.getstatusoutput(cmd)
- subprocess.getoutput(cmd)
- 使用举例以及注意事项
注:本文只介绍 python3.6+
Windows 调用外部程序
可以使用 win32process 模块中的函数。如果想进一步控制进程,则可以使用 ctype 模块,直接调用 kernel32.dll 中的函数
- 使用 os.system 函数运行其他程序
- 使用 ShellExecute 函数运行其他程序
- 使用 CreateProcess 函数运行其他程序
- 使用 ctypes 调用 kernel32.dll 中的函数
import os
import win32api
import win32process
import win32event
os.system(command)
说明:
- 等待执行
- 正常结束返回 0
或者 os.popen(command), 详细讲解见下文
用法举例
import os
# 打开记事本程序
os.system('notepad')
# 关闭记事本后的返回值 0
0
# 向记事本传递参数,打开python.txt文件
os.system('notepad python.txt')
0
win32api.ShellExecute(hwnd, op , file , params , dir , bShow )
参数:
- hwnd:父窗口的句柄,如果没有父窗口,则为 0。
- op:要进行的操作,为“open”、“print”或者为空。
- file:要运行的程序,或者打开的脚本。
- params:要向程序传递的参数,如果打开的为文件,则为空。
- dir:程序初始化的目录。
- bShow:是否显示窗口。
说明:
- 不用等待
- 相当于在资源管理器中双击文件图标一样,系统会打开相应的应用程序执行操作
用法举例
import win32api
打开记事本程序,在后台运行,即显示记事本程序的窗口
win32api.ShellExecute(0, 'open', 'notepad', '', '', 0)
42
打开记事本程序,在前台运行
win32api.ShellExecute(0, 'open', 'notepad.exe', '', '', 1)
42
向记事本传递参数,打开 python.txt
win32api.ShellExecute(0, 'open', 'notepad.exe', 'python.txt', '', 1)
42
在默认浏览器中打开http://www.python.org网站
win32api.ShellExecute(0, 'open', 'http://www.python.org', '', '', 1)
42
在默认的媒体播放器中播放 E:\song.wma
win32api.ShellExecute(0, 'open', 'E:\\song.wma', '', '', 1)
运行位于 E:\book\code 目录中的 MessageBox.py 脚本
win32api.ShellExecute(0, 'open', 'E:\\book\\code\\MessageBox.py', '', '', 1)
win32process.CreateProcess 创建进程
形式:
CreateProcess(appName, commandLine , processAttributes , threadAttributes , bInheritHandles ,dwCreationFlags , newEnvironment , currentDirectory , startupinfo )
参数:
- appName:可执行的文件名。
- commandLine:命令行参数。
- processAttributes:进程安全属性,如果为 None,则为默认的安全属性。
- threadAttributes:线程安全属性,如果为 None,则为默认的安全属性。
- bInheritHandles:继承标志。
- dwCreationFlags:创建标志。
- newEnvironment:创建进程的环境变量。
- currentDirectory:进程的当前目录。
- startupinfo :创建进程的属性。
说明:
- 不用等待
- 可通过句柄控制终止、等待
import win32process
handle = win32process.CreateProcess('c:\\windows\\notepad.exe', '', None, None,
0, win32process.CREATE_NO_WINDOW, None,
None, win32process.STARTUPINFO())
终止控制 win32process.TerminateProcess
参数:
- handle:要操作的进程句柄。
- exitCode:进程退出代码。
handle = win32process.CreateProcess('c:\\windows\\notepad.exe', '', None, None,
0, win32process.CREATE_NO_WINDOW, None,
None, win32process.STARTUPINFO())
win32process.TerminateProcess(handle[0], 0)
等待控制 win32event.WaitForSingleObject
参数:
- handle:要操作的进程句柄。
- milliseconds:等待的时间,如果为 1,则一直等待。
返回值 0
handle = win32process.CreateProcess('c:\\windows\\notepad.exe', '', None, None,
0, win32process.CREATE_NO_WINDOW, None,
None, win32process.STARTUPINFO())
# 等待进程结束, 等待时间 默认 -1(永远)
win32event.WaitForSingleObject(handle[0], -1)
# 进程结束的返回值
0
使用 ctypes 调用 kernel32.dll 中的函数
使用 ctypes 模块可以使 Python 调用由 C 语言编写的动态链接库,并向其传递参数。
ctypes 定义了 C 语言中的基本数据类型,并且可以实现 C 语言中的结构体和联合体。ctypes 可以工作在 Windows、Windows CE、Mac OS X、Linux、Solaris、FreeBSD、OpenBSD 等平台上,基本上实现了跨平台
在 Windows 下直接调用 user32.dll 中的 MessageBoxA 函数:
from ctypes import *
user32 = windll.LoadLibrary('user32.dll') # 加载动态链接库
# 调用MessageBoxA函数.
user32.MessageBoxA(0, b'Ctypes is cool!', 'Ctypes', 0)
1
OS 模块
os.system(command)
- 等待执行
- 有返回值
- 输出流不可捕获
翻译如下:
在子 shell 中执行命令(参数:字符串)。这是通过调用标准 C 函数系统()来实现的,并且具有相同的限制。
改变 sys.stdin (,etc) 不会在执行此次命令中生效。如果 command 生成任何输出,它将被发送到解释器标准输出流。(即,所有输出信息都会显示到命令行中)
在 Unix 上,返回值是以 wait()指定的格式编码的进程的退出状态。请注意,POSIX 未指定 C 语言 system()函数的返回值的含义,因此 Python 函数的返回值取决于系统。
在 Windows 上,返回值是运行命令后系统 shell 返回的值。shell 由 Windows 环境变量 COMSPEC 给出:它通常是 cmd.exe,它返回命令运行的退出状态;在使用非本机 shell 的系统上,请参阅 shell 文档。
subprocess 模块提供了更强大的工具来生成新进程并检查其结果;使用该模块比使用 os.system 更可取。
用法举例
import os
# 打开记事本程序
os.system('notepad')
# 关闭记事本后的返回值 0
0
os.popen
- 不用等待,读取结果 stdout 需要等待
- 返回管道(IO 包装对象,类似文件对象),可 read()、readline() 等
本质是使用 subprocess.Popen 方法实现
同样的,官方推荐使用 subprocess 代替此方法。
底层实现如下:
Signature: os.popen(cmd, mode='r', buffering=-1)
Docstring: <no docstring>
Source:
def popen(cmd, mode="r", buffering=-1):
if not isinstance(cmd, str):
raise TypeError("invalid cmd type (%s, expected string)" % type(cmd))
if mode not in ("r", "w"):
raise ValueError("invalid mode %r" % mode)
if buffering == 0 or buffering is None:
raise ValueError("popen() does not support unbuffered streams")
import subprocess, io
if mode == "r":
proc = subprocess.Popen(cmd,
shell=True,
stdout=subprocess.PIPE,
bufsize=buffering)
return _wrap_close(io.TextIOWrapper(proc.stdout), proc)
else:
proc = subprocess.Popen(cmd,
shell=True,
stdin=subprocess.PIPE,
bufsize=buffering)
return _wrap_close(io.TextIOWrapper(proc.stdin), proc)
File: d:\softinstall\anacoda3\lib\os.py
import os
os.popen??
用法举例
import os
p = os.popen('ping www.baidu.com')
p
<os._wrap_close at 0x2b6682f4080>
等待进程执行完毕后才可读出执行结果(阻塞)
print(p.read())
正在 Ping www.baidu.com [180.101.49.11] 具有 32 字节的数据:
来自 180.101.49.11 的回复: 字节=32 时间=119ms TTL=53
来自 180.101.49.11 的回复: 字节=32 时间=343ms TTL=53
来自 180.101.49.11 的回复: 字节=32 时间=58ms TTL=53
来自 180.101.49.11 的回复: 字节=32 时间=187ms TTL=53
180.101.49.11 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 58ms,最长 = 343ms,平均 = 176ms
# 输入一个错误命令
p = os.popen('notepada')
p.read()
# 没有错误信息, 原因见上面实现代码
''
说明:
以上两个方法的 subprocess 替代用法,见官方连接:
Replacing Older Functions with the subprocess Module
subprocess 模块
Popen–最基本的类
说明:创建一个新的进程执行命令,返回一个实例,进行后续操作
本质:
在 POSIX,此类使用类似于 os.execvp() 的行为来执行子程序。
在 Windows,此类使用了 Windows CreateProcess() 函数。
- 非阻塞,可以 wait()等待.
- 支持多种参数和模式,方便控制和进程交互
- 可捕获运行输出和返回状态码
Popen 原型是:
Popen(args, bufsize=-1, executable=None,
stdin=None, stdout=None, stderr=None,
preexec_fn=None, close_fds=True,
shell=False, cwd=None, env=None, universal_newlines=None,
startupinfo=None, creationflags=0,
restore_signals=True, start_new_session=False,
pass_fds=(), *, encoding=None, errors=None, text=None)
参数:
args
: 一个字符串命令,或者参数序列(最终还是转为一个字符串)。提供一个参数序列通常更好,它可以更小心地使用参数中的转义字符以及引用(例如允许文件名中的空格)。如果传递一个简单的字符串,则 shell 参数(Linux 下)必须为 True,或者用 executable 参数指定运行该命令的程序。
参数既可以是 string,也可以是 list。
对于参数是字符串,需要指定 shell=True
subprocess.Popen([“cat”,”test.txt”])
subprocess.Popen(“cat test.txt”, shell=True)
linux 下如果传入一个序列,则该序列的第一个元素默认当作执行后续参数的程序,比如:
cmd = [“ssh”, 'root@192.168.1.2"]
则用 ssh 去执行后续参数
-
bufsize
:当创建 stdin/stdout/stderr 管道文件时,为 open() 方法提供 buffering 参数 z -
executable
:用于指定可执行程序。一般情况下我们通过 args 参数来设置所要运行的 shell 程序。如果将参数 shell 设为 True,executable 将指定程序使用的 shell。在 windows 平台下,默认的 shell 由 COMSPEC 环境变量来指定。(比如 cmd.exe) -
stdin, stdout, stderr
分别表示程序的标准输入、输出、错误句柄。他们可以是:- PIPE
- 文件描述符
- 文件对象,
- None,表示从父进程继承。
stderr
还可以设置为subprocess.STDOUT
。
-
preexec_fn
:钩子函数,只在 Unix 平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用 -
close_fds
:控制关闭或者继承文件描述符。在 windows 平台下,如果 close_fds 被设置为True,则新创建的子进程将不会继承父进程的输入、输出、错误管道。我们不能将 close_fds 设置为 True 同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。 -
shell
:如果设为True
,unix 下相当于args
前面添加了 “/bin/sh” “-c” ,Windows 下相当于添加了 “cmd.exe /c” -
cwd
:用于设置子进程的当前目录 -
env
:字典类型,用于指定子进程的环境变量。如果 env = None,子进程的环境变量将从父进程中继承 -
universal_newlines
:控制统一换行符。不同操作系统下,文本的换行符是不一样的。如:windows 下用’\r\n’表示换,而 Linux 下用 ‘\n’。如果将此参数设置为 True,Python 统一把换行符处理为’\n’。 -
startupinfo
: 只在 windows 下用效,传递给底层 CreateProcess()的结构体,用 于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等 -
creationflags
: 只在 windows 下用效, 传递给CREATE_NEW_CONSOLE
创建自己的控制台窗口 -
restore_signals
:POSIX only -
start_new_session
:POSIX only -
pass_fds
:POSIX only -
encoding
anderrors
: 文件对象stdin、stdout、和stderr
的解码方式,以及解码的处理方式(比如:ignore、strict,参考encode()
) -
text
:如果设为True
,用给定的encoding
参数解码 stdin, stdout and stderr,如果encoding
未指定,则使用系统默认编码。
基本用法
此例是在 windows 上执行一条错误命令 notepad(打开记事本)。
注意:
如果不设置 stderr=subprocess.PIPE,则获取不到错误信息
communicate() 方法见下文。
import subprocess
p = subprocess.Popen('notepada',
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
# 注意解码Windows上默认 gbk,换行符为 \r\n
stdoutdata, stderrdata = p.communicate()
stdoutdata.decode('gbk')
''
stderrdata.decode('gbk')
"'notepada' 不是内部或外部命令,也不是可运行的程序\r\n或批处理文件。\r\n"
指定编码方式 或者 统一换行符参数都会将输出流编码
p = subprocess.Popen('notepada',
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE, encoding='gbk')
# p = subprocess.Popen('notepada',
# shell=True,
# stdout=subprocess.PIPE,
# stderr=subprocess.PIPE, universal_newlines=True)
stdoutdata, stderrdata = p.communicate()
stdoutdata, stderrdata
('', "'notepada' 不是内部或外部命令,也不是可运行的程序\n或批处理文件。\n")
Popen 的常用方法
Popen.poll()
用于检查子进程是否已经结束。
- 不会等待进程
- 进程未结束返回
None
- 进程结束返回 returncode。
p.poll()
Popen.wait(timeout=None)
在规定时间内等待进程结束,设置 timeout=None,则一直等待直到结束
返回:returncode
p.wait()
Popen.communicate(input=None)
功能:
-
等待进程结束
-
与子进程进行交互。向
stdin
发送数据并关闭它。可选参数input
指定发送到子进程的数据,注意Popen
对象的**encoding
或者text
参数**决定传入字符串还是字节流。 -
从
stdout
和stderr
中读取数据, 并关闭。
如果没有数据发送到子进程(stdin
),则返回一个元组:(stdoutdata, stderrdata)。
注意:
如果希望通过进程的stdin
向其发送数据,在创建Popen
对象的时候,参数stdin
必须被设置为PIPE
。同样,如果希望从stdout
和stderr
获取数据,必须将stdout
和stderr
设置为PIPE
。
警告:
使用 communicate()而不是.stdin.write,.stdout.read 或.stderr.read 来避免由于任何其他 OS 管道缓冲区填满和阻止子进程而导致的死锁
Popen.send_signal(sig)
向进程发送信号(方法内部自行检查进程是否已经终止,已经终止是不会响应信号的)
import signal
两种情况的参数:
Windows 上:
- 终止:signal.SIGTERM
- Ctrl + C:signal.CTRL_C_EVENT
- Ctrl + Break:signal.CTRL_BREAK_EVENT
Linux 上:
- 终止:signal.SIGTERM 或者 signal.SIGKILL
例如:
import signal
p.send_signal(signal.SIGTERM)
Popen.terminate()
停止子进程。在 Posix 操作系统上,此方法发送 SIGTERM
。在 Windows,调用 Win32 API 函数 TerminateProcess()
来停止子进程
Popen.kill()
在 Posix 操作系统上,此函数给子进程发送 SIGKILL
信号。在 Windows 上, kill()
是 terminate()
的别名。
Popen 的属性
Popen.stdin
-
如果
stdin
参数为PIPE
,此属性是一个类似open()
返回的可写的流对象。 -
如果
encoding
或errors
参数被指定或者universal_newlines
参数为True
,则此流是一个字符串,否则是字节流。 -
如果
stdin
参数非PIPE
, 此属性为None
。
Popen.stdout
-
如果
stdin
参数为PIPE
,此属性是一个类似open()
返回的可读的流对象。 -
如果
encoding
或errors
参数被指定或者universal_newlines
参数为True
,则此流是一个字符串,否则是字节流。 -
如果
stdin
参数非PIPE
, 此属性为None
。
Popen.stderr
-
如果
stdin
参数为PIPE
,此属性是一个类似open()
返回的可读的流对象。 -
如果
stdin
参数为subprocess.STDOUT
,则错误输出到 stdout。 -
如果
encoding
或errors
参数被指定或者universal_newlines
参数为True
,则此流是一个字符串,否则是字节流。 -
如果
stdin
参数非PIPE
, 此属性为None
。
Popen.pid
获取子进程的进程 ID。
Popen.returncode
获取进程的返回值。如果进程还没有结束,返回 None。
常量
subprocess.PIPE
在创建Popen
对象时,subprocess.PIPE
可以初始化stdin, stdout
或stderr
参数,表示与子进程通信的标准流。如果希望从stdout和stderr
获取数据,必须将stdout和stderr
设置为subprocess.PIPE
。
subprocess.STDOUT
创建 Popen 对象时,用于初始化 stderr 参数,表示将错误通过标准输出流输出。
subprocess.STD_INPUT_HANDLE
标准输入设备,初始化时,是从 console 控制台输入
subprocess.STD_OUTPUT_HANDLE
标准输出设备,初始化时,是活动 console 屏幕缓冲区
subprocess.STD_ERROR_HANDLE
标准错误输出设备,初始化时,同样是 console 屏幕缓冲区。
subprocess.SW_HIDE
隐藏窗口。另一个窗口将被激活
subprocess.CREATE_NEW_CONSOLE
新进程有一个新的控制台,而不是继承其父控制台(默认)。当使用 shell = True 创建 Popen 时,始终设置此标志。
基于 Popen 的其他方法
subprocess.call(*popenargs, timeout=None, **kwargs)
说明:
仅能执行命令和获取执行的返回码,和超时控制,没有其他功能。不能捕获输出流。
- 使用参数运行命令
- 等待完成
- 返回 returncode 属性。
- 超时触发
TimeoutExpired
异常
参数:
同Popen构造函数
timeout:秒,用于等待完成,超时强制退出,释放所有资源
本质:
使用上下文管理器(with 语句):调用Popen(),以及Popen.wait(timeout)等待完成.
警告:
当输出数据较大时会发生死锁,用communicate()来避免。
示例:
retcode = subprocess.call(["ls", "-l"], shell=True)
retcode
1
subprocess.check_call(*popenargs, **kwargs)
说明:
在上面的 call()方法上加了 检查功能
- 等待完成
- 执行无误返回 0,否则引发
CalledProcessError
。
参数:
同subprocess.call()
本质:
调用上面的call() 方法并在结束后检查 returncode是否为0.
警告:
当输出数据较大时会发生死锁,用communicate()来避免。
subprocess.check_call('calc')
0
subprocess.check_call(["ls", "-l"], shell=True)
---------------------------------------------------------------------------
CalledProcessError Traceback (most recent call last)
<ipython-input-25-e737dd244224> in <module>
----> 1 subprocess.check_call(["ls", "-l"], shell=True)
D:\SoftInstall\Anacoda3\lib\subprocess.py in check_call(*popenargs, **kwargs)
345 if cmd is None:
346 cmd = popenargs[0]
--> 347 raise CalledProcessError(retcode, cmd)
348 return 0
349
CalledProcessError: Command '['ls', '-l']' returned non-zero exit status 1.
CompletedProcess 类
(下面两个方法要用到)
run()方法的返回值
属性:
-
args:进程执行的命令,str 或者 list
-
returncode:结束返回值
-
stdout:标准输出
-
stderr:标准错误
方法:
- check_returncode(): 检查 returncode 退出码,如果不是 0,引发 CalledProcessError 异常。
subprocess.run(*popenargs, input=None, capture_output=False, timeout=None, check=False, **kwargs):
说明:
可从返回的 CompletedProcess 的实例中获取 returncode、stdout、stderr 属性
- 等待结束,或者超时异常
- 超时控制
- 结果检查
- 进程安全,结束、异常终止都释放所占用资源
- 在不超时,不检查 returncode,或者 returncode 为 0 的情况下返回 CompletedProcess 实例,否则直接异常退出
参数
-
与
Popen
的参数通用 -
input
:向进程通信传入的数据,bytes 或者 str。如果不为 None,则不能再传入stdin
参数 -
capture_output
:如果设置为True
,就不能再传入stdout
和stderr
参数,否则报错 -
timeout
:限制执行时间,超时引发TimeoutExpired
异常。默认为一直等待到执行结束 -
check
:是否检查 returncode,如果不为 0,引发CalledProcessError
异常 (可以先不检查,在返回的 CompletedProcess 实例中调用 check_returncode 方法再检查)
本质:
使用Popen的with语句,和communicate()方法等待结束,并加入了超时控制和返回码检查,捕获输出更加简单,是对Popen用法的封装,功能较全。
subprocess.check_output(*popenargs, timeout=None, **kwargs)
说明:执行命令,当命令执行成功(returncode=0)且未超时时,只返回 stdout 输出。
- 与上述 run 类似
- 运行失败引发
CalledProcessError
异常 - 运行成功直接返回 stdout
参数:
- 与 run() 通用
- 不允许设置
stdout
参数
本质:
subprocess.run(…).stdout
疑问
如下:
查看 java 版本命令返回码为 0 ,但是输出到了标准错误流中,求告知。
subprocess.check_output(['java', '-version'])
b''
a = subprocess.run(['java', '-version'], capture_output=True, universal_newlines=True)
print(a.stderr)
java version "1.8.0_202"
Java(TM) SE Runtime Environment (build 1.8.0_202-b08)
Java HotSpot(TM) Client VM (build 25.202-b08, mixed mode)
a = subprocess.Popen(['java', '-version'], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
a.communicate()
('',
'java version "1.8.0_202"\nJava(TM) SE Runtime Environment (build 1.8.0_202-b08)\nJava HotSpot(TM) Client VM (build 25.202-b08, mixed mode)\n')
subprocess.getstatusoutput(cmd)
说明:执行命令,成功后(returncode=0)返回一个元组(返回码,所有输出信息)
参数:
- cmd:执行的命令
本质:
调用 check_out()方法,并设置参数shell=True, text=True, stderr=STDOUT
即将 stderr 重定向到标准输出,得到的是所有输出信息
得到的输出信息较完整,且调用方便,建议使用
subprocess.getstatusoutput(['java', '-version'])
(0,
'java version "1.8.0_202"\nJava(TM) SE Runtime Environment (build 1.8.0_202-b08)\nJava HotSpot(TM) Client VM (build 25.202-b08, mixed mode)')
subprocess.getoutput(cmd)
本质:调用subprocess.getstatusoutput
,只取输出
getstatusoutput(cmd)[1]
subprocess.getoutput(['python', '-V'])
'Python 3.7.3'
使用举例以及注意事项
- 使用 communicate 等待完成并获取输出,而不用其他的等待方法,避免发生系统 IO 阻塞(output 数据太多)
- 参数 shell=True 在所执行的命令从 input() 输入的时候可能遭受 shell 注入攻击
- 获取输出要与系统默认编码一致
如果超时到期,子进程不会被杀死,所以为了正确清理一个行为良好的应用程序应该杀死子进程并完成通讯
proc = subprocess.Popen(...)
try:
outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
proc.kill()
outs, errs = proc.communicate()
在 POSIX 上建议 cmd 命令传入一个序列,而不是字符串,尤其是在复杂的情形下。
可以用 shellx.split(),方法将字符串安全正确的转换为一个列表序列:
>>> import shlex, subprocess
>>> command_line = input()
/bin/vikings -input eggs.txt -output "spam spam.txt" -cmd "echo '$MONEY'"
>>> args = shlex.split(command_line)
>>> print(args)
['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "echo '$MONEY'"]
>>> p = subprocess.Popen(args) # Success!
在 windows 上序列会先转为字符串再执行
修改linux账户密码(向进程输入,注意使用回车\n)
subprocess.run('sudo passwd root', input=b'123\n123', shell =True)
输入新的 UNIX 密码:重新输入新的 UNIX 密码:passwd:已成功更新密码
执行结果保存在文件
cmd = 'ping www.baidu.com'
fhandle = open("aa.txt", "w")
pipe = subprocess.Popen(cmd, shell=True, stdout=fhandle)
fhandle.close()
执行结果使用管道输出
output = subprocess.Popen(["python", "-V"], stdout=subprocess.PIPE).communicate()[0]
output
b'Python 3.7.3\r\n'
pipe = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, encoding='gbk').stdout
print(pipe.read())
正在 Ping www.a.shifen.com [180.101.49.11] 具有 32 字节的数据:
来自 180.101.49.11 的回复: 字节=32 时间=97ms TTL=53
来自 180.101.49.11 的回复: 字节=32 时间=116ms TTL=53
来自 180.101.49.11 的回复: 字节=32 时间=145ms TTL=53
来自 180.101.49.11 的回复: 字节=32 时间=261ms TTL=53
180.101.49.11 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 97ms,最长 = 261ms,平均 = 154ms
代替 shell 管道符
查看 python 进程
ps -ef |grep python
p1 = subprocess.Popen(["ps", "-ef"], stdout=subprocess.PIPE)
p2 = subprocess.Popen(["grep", "hda"], stdin=p1.stdout, stdout=subprocess.PIPE)
p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0]
选择执行程序
在 windows 上使用 Git 的执行 shell 命令
exe_path = r'D:\SoftInstall\Git\git-cmd.exe'
p = subprocess.Popen('ifconfig',
executable=exe_path,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True)
p.communicate()
# 好像没有什么卵用
('\nD:\\OneDrive - business\\jupyter notebook\\Modules-Learn>', '')
传入环境变量
subprocess.Popen(["/bin/mycmd", "myarg"], env={"PATH": "/usr/bin"})