os.system与os.popen区别
1.os.system
其返回值是脚本的退出状态码,0表示成功,其他均为失败。
os.system(command):该方法在调用完shell脚本后,返回一个16位的二进制数,低位为杀死
所调用脚本的信号号码,高位为脚本的退出状态码,即脚本中“exit 1”的代码执行后,
os.system函数返回值的高位数则是1,如果低位数是0的情况下,则函数的返回值是0x0100,
换算为十进制得到256。
system函数可以将字符串转化成命令在服务器上运行;其原理是每一条system函数执行时,
其会创建一个子进程在系统上执行命令行,子进程的执行结果无法影响主进程。
但是上述原理会导致当需要执行多条命令行的时候可能得不到预期的结果。
因此为了保证system执行多条命令可以成功,多条命令需要在同一个子进程中运行。
如:
1 import os
2 os.system('cd /usr/local && mkdir aaa.txt')# 或者os.system('cd /usr/local ; mkdir aaa.txt')
2. os.popen
其方法用于从一个命令打开一个管道,在Unix,Windows中有效。
popen()方法语法格式如下:
os.popen(command[, mode[, bufsize]])
参数
command – 使用的命令。
mode – 模式权限可以是 ‘r’(默认) 或 ‘w’。
bufsize – 指明了文件需要的缓冲大小:0意味着无缓冲;1意味着行缓冲;
其它正值表示使用参数大小的缓冲(大概值,以字节为单位)。负的bufsize
意味着使用系统的默认值,一般来说,对于tty设备,它是行缓冲;对于其
它文件,它是全缓冲。如果没有改参数,使用系统的默认值。
返回值
返回一个文件描述符号为fd的打开的文件对象。
返回值是文件对象
注意:返回值是文件对象,既然是文件对象,使用完就应该关闭,对吧?!不信网上搜一下,
一大把文章提到这个os.popen都是忘记关闭文件对象的。所以,推荐的写法是:
with os.popen(command, "r") as p:
r = p.read()
至于with的用法就不多讲了,使用它,不需要显式的写p.close()。
2.非阻塞
通俗的讲,非阻塞就是os.popen不会等cmd命令执行完毕就继续下面的代码了,不信?!看下面代码实例:
import os
os.popen(r"D:\Program Files (x86)\Tencent\QQ\Bin\QQScLauncher.exe")
print("测试开发小白便怪兽")
从上面实例可知,os.popen执行打开QQScLauncher.exe这个工具,但从实际执行结果看,
QQScLauncher.exe还没打开,就直接进入了下一条语句,打印了“测试开发小白变怪兽”。
在某些应用场景,可能这并不是你期望的行为,那如何让命令执行完后,再执行下一句呢?
处理方法是使用read()或readlines()对命令的执行结果进行读操作。
3.完全阻塞
上面写了该函数是非阻塞的,现在怎么又变成完全阻塞的呢?感觉一头雾水了吧。本质上
os.popen是非阻塞的,为了实现阻塞的效果,我们使用read()或readlines()对命令结果
进行读,由此产生了阻塞的效果。但是,如果你的命令执行无法退出或进入交互模式,
这种“读”将形成完全阻塞的情况,表现的像程序卡住了。
看下面代码实例:
import os
ret = os.popen("ping 127.0.0.1 -t")
ret.readlines()
os.popen执行了ping 127.0.0.1 -t 该命令会一直执行,除非CTRL+C强制退出,因而,执行readlines读取命令输出时会造成卡住。
总结
os.popen()在大多数场景都是挺好用方便的,但是也有坑!!具体应用中,需要注意下:
1. 在需要读取命令执行结果时,避免在命令无法退出或进入交互模式的场景应用os.popen;
2.os.popen()无法满足需求时,可以考虑subprocess.Popen();
摘自: