Python执行系统命令的三种核心方法详解
本文深入解析Python中执行外部命令的三种主要方式:os.system、os.popen/subprocess.Popen以及commands模块。详细对比了各方法的返回值处理机制、阻塞特性及适用场景,重点剖析了Popen类的参数配置与常用方法,帮助开发者根据实际需求选择最高效的命令执行方案。
Python执行系统命令概述
在Python开发中,调用操作系统命令是常见需求。目前主要使用的执行方式有三种,分别适用于不同的场景和复杂度要求。
方法一:os.system
第一种方法是使用 os.system("cmd") 函数。
该函数在调用完shell脚本后,返回一个16位的整数。其中,低8位表示杀死所调用脚本的信号号码,高8位表示脚本的退出状态码。例如,如果脚本中执行了“exit 1”,则 os.system 函数返回值的高8位为1;若低8位为0,则函数返回值为 0x100,换算为十进制即256。
若需获取 os.system 的正确退出状态码,可通过位移运算还原:
>>> n = os.system(test.sh)
>>> n >> 8
>>> 3
这是最简单的一种方法,其特点是在执行时会打印出Linux系统上cmd命令的执行信息。使用前需导入 os 模块。
os.system("ls") 仅在一个子终端中运行系统命令,且无法直接获取命令执行后的返回内容。
方法二:os.popen
第二种方法涉及 os.popen。
这种调用方式通过管道机制实现,函数返回一个类似文件对象(file-like object),其中包含脚本输出的内容(可简单理解为echo输出的内容)。使用 os.popen 调用 test.sh 的情况如下:Python调用Shell脚本主要有两种方法:os.system(cmd) 或 os.popen(cmd)。前者返回脚本的退出状态码,后者返回脚本执行过程中的输出内容。实际使用时应根据需求选择。显然,对于调用“ls”这类需要获取输出内容的shell命令,应使用 popen 方法。
popen(command [, mode='r' [, bufsize]]) -> pipe
tmp = os.popen('ls *.py').readlines()
方法三:subprocess.Popen详解
第三种方法推荐使用 subprocess.Popen。
目前大多数开发者倾向于使用 Popen。Popen 方法不会打印出cmd在Linux上执行时的中间信息。确实,Popen 功能强大,支持多种参数和模式。使用前需导入:from subprocess import Popen, PIPE。但 Popen 函数有一个缺陷,即它是阻塞式的。如果运行cmd时产生的内容非常多,函数容易阻塞。解决办法是不使用 wait() 方法,但这样也无法直接获得执行的返回值。
Popen 的原型定义如下:
subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=false)
参数 bufsize:指定缓冲大小。具体含义尚需进一步探讨,欢迎有经验者指点。
参数 executable 用于指定可执行程序。一般情况下,我们通过 args 参数来设置要运行的程序。如果将参数 shell 设为 True,executable 将指定程序使用的shell。在Windows平台下,默认的shell由 COMSPEC 环境变量指定。
参数 stdin, stdout, stderr 分别表示程序的标准输入、输出、错误句柄。它们可以是 PIPE,文件描述符或文件对象,也可以设置为 None,表示从父进程继承。
参数 preexec_fn 仅在Unix平台下有效,用于指定一个可调用对象(callable object),它将在子进程运行之前被调用。
参数 close_fds:在Windows平台下,如果 close_fds 被设置为 True,则新创建的子进程将不会继承父进程的输入、输出、错误管道。注意:不能将 close_fds 设置为 True 同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。
如果参数 shell 设为 true,程序将通过shell来执行命令。
参数 cwd 用于设置子进程的当前工作目录。
参数 env 是字典类型,用于指定子进程的环境变量。如果 env = None,子进程的环境变量将从父进程中继承。
参数 Universal_newlines:不同操作系统下,文本的换行符不同。例如:Windows下用 '/r/n' 表示换行,而Linux下用 '/n'。如果将此参数设置为 True,Python 统一把这些换行符当作 '/n' 来处理。
参数 startupinfo 与 creationflags 仅在Windows下有效,它们将被传递给底层的 CreateProcess() 函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等。
subprocess.PIPE 在创建 Popen 对象时,subprocess.PIPE 可以初始化 stdin, stdout 或 stderr 参数,表示与子进程通信的标准流。
subprocess.STDOUT 创建 Popen 对象时,用于初始化 stderr 参数,表示将错误通过标准输出流输出。
Popen 类提供的常用方法如下:
Popen.poll() 用于检查子进程是否已经结束。设置并返回 returncode 属性。
Popen.wait() 等待子进程结束。设置并返回 returncode 属性。
Popen.communicate(input=None) 与子进程进行交互。向stdin发送数据,或从stdout和stderr中读取数据。可选参数 input 指定发送到子进程的数据。Communicate() 返回一个元组:(stdoutdata, stderrdata)。注意:如果希望通过进程的stdin向其发送数据,在创建Popen对象时,参数stdin必须被设置为PIPE。同样,如果希望从stdout和stderr获取数据,必须将stdout和stderr设置为PIPE。
Popen.send_signal(signal) 向子进程发送信号。
Popen.terminate() 停止(stop)子进程。在Windows平台下,该方法将调用Windows API TerminateProcess()来结束子进程。
Popen.kill() 杀死子进程。
Popen.stdin 如果在创建Popen对象时,参数stdin被设置为PIPE,Popen.stdin 将返回一个文件对象用于向子进程发送指令。否则返回None。
Popen.stdout 如果在创建Popen对象时,参数stdout被设置为PIPE,Popen.stdout 将返回一个文件对象用于从子进程读取指令。否则返回None。
Popen.stderr
如果在创建Popen对象时,参数stderr被设置为PIPE,Popen.stderr 将返回一个文件对象用于从子进程读取错误信息。否则返回None。
Popen.pid 获取子进程的进程ID。
Popen.returncode 获取进程的返回值。如果进程还没有结束,返回None。
以下是一个使用示例:
p = Popen("cp -rf a/* b/", shell=True, stdout=PIPE, stderr=PIPE)
p.wait()
if p.returncode != 0:
print "Error."
return -1
方法四:commands模块
第三种方法是使用 commands.getstatusoutput 方法。
这个方法也不会打印出cmd在Linux上执行的信息。该方法唯一的优点是,它不是阻塞式的,即不存在Popen函数可能出现的阻塞问题。使用前需导入 commands 模块。
例如:
status, output = commands.getstatusoutput("ls")
还有只获得output和status的方法:
commands.getoutput("ls")
commands.getstatus("ls")
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













