Python 编程中可能会需要调用系统命令。本文以一段测试网络连通性的代码来演示如何执行系统命令,并获取输出结果。
教程 os.system😐import os
def ping(ip):
os.system(f'ping {ip}')
if __name__=='__main__':
ping(input('please enter the ip to ping: '))
执行上述代码,输入 baidu.com
并回车,控制台就会打印 ping
结果。
os.system
调用标准 C 函数来实现命令在子进程中执行。它会将命令执行的任何输出重定向到解释器(我们这里是 Python 解释器)的标准输出流。其返回值是进程的退出码,反映进程的退出状态,在 Windows 和 Unix 系统上会有所不同。实测是 Windows 系统上的退出码是 0,表示命令成功执行并关闭进程。
>>> import os
>>> os.system('pwd')
/c/Users/87897/Desktop
0
os.popen😊
os.system
函数返回值是进程退出码,无法获取命令执行输出结果。而 os.popen
通过管道的方式连接到执行进程,可灵活地获得命令执行的输出。其返回值是一个连接到管道的打开文件对象,可以根据模式是 r
(默认值) 还是 w
来读取或写入。
根据 os.popen 的特性,我们可以将上述代码简单变动一下:不在控制台打印 ping 结果,而是将其保存在一个名为 ping.log
的日志文件中,方便后续的 debug 或审查。
import os
def ping(ip):
with open('ping.log', 'a', encoding='utf-8') as fw:
with os.popen(f'ping {ip}', mode='r') as fr:
fw.write(fr.read())
if __name__ == '__main__':
ping(input('please enter the ip to ping: '))
subprocess😁
import subprocess
def ping(ip):
p = subprocess.run(
f'ping {ip}',
capture_output=True,
text=True
)
return p.stdout
if __name__ == '__main__':
print(ping(input('please enter the ip to ping: ')))
官方开发 subprocess
模块就是为了替换 os.system
和 os.popen
,因此更推荐使用 subprocess
。通过 subprocess.run
函数开一个子进程来执行系统命令。如果指定 capture_output=True
,将返回一个 CompletedProcess
的类实例,该类的 stdout
属性可查看命令的输出结果。
如果想让一行执行多条关联命令,比如:先 cd
到一个目录,然后在该目录下新建文件夹,可以用 &
符号将多条命令连接起来,实例代码如下。
import os
def func():
os.system('cd test & mkdir main')
if __name__=='__main__':
func()
如果多条命令没有依赖关系的话,直接多调用几次函数,然后从上到下顺序执行。
如果执行的命令的时候需要进行人机交互(例如 SSH 远程连接服务器时需要输入密码),可以考虑使用 pexpect 库,这是一个 Python 第三方库,用来启动一个子进程,并对其进行自动化控制。其常规用法如下:
- 使用
spawn
方法来执行程序 - 使用
expect
方法等待程序打印输入提示关键字 - 使用
send/sendline
方法发送字符串到程序
但该库目前仅支持 Unix 系统,对 Windows 系统的支持非常有限,请根据需求选择。
注意上述所有执行系统命令的方式都有被注入恶意脚本的风险。因此,在实际应用场景下,要设置过滤策略,进行代码漏洞排查。
例如,下方的代码就在 ping
的同时添加了一条删除整个 test
文件夹的命令:
import os
def ping(ip):
os.system(f'ping {ip} & rm -rf test/')
if __name__ == '__main__':
ping(input('please enter the ip to ping: '))
如果把 rm -rf test/
改为 rm -rf /
,那就是删除整个系统文件了,所以一定要慎用!
os.system 官方文档 os.popen 官方文档 subprocess 官方文档 Python学习之OS库的system函数 Python模块Pexpect详解 python pexpect模块的使用