有时候我们需要从Python中执行Linux命令,下面就介绍几种方法?
1. os 模块:
1.1 os.system 函数:
system方法会创建子进程运行外部程序,方法只返回外部程序的运行结果。这个方法比较适用于外部程序没有输出结果的情况。
>>> os.system('echo \ "Hello World\"') #直接使用os.system调用一个echo命令
Hello World
0>>> os.system("cat /proc/meminfo")
MemTotal:486640kB
MemFree:301184kB
Buffers:10304kB
Cached:58316kB
SwapCached: 0 kB
Active:43748kB
Inactive:45336kB
Active(anon):20476kB
Inactive(anon):520kB
Active(file):23272kB
Inactive(file):44816 kB
注意:上面说了,此方法只会外部程序的结果,也就是os.system的结果,所以如果你想接收命令的返回值,接着向下看
1.2os模块的popen方法
当需要得到外部程序的输出结果时,本方法非常有用,返回一个类文件对象,调用该对象的read()或readlines()方法可以读取输出内容。
>>> print(os.popen('ls -lt')) # 是以一个类文件对象的形式
>>> print(os.popen('ls -lt').read())
总用量98drwxr-xr-x. 2 root root 4096 5月 19 04:26opt
dr-xr-x---. 3 root root 4096 5月 19 04:26root
drwxr-xr-x. 19 root root 3760 5月 19 04:22dev
drwxr-xr-x. 78 root root 4096 5月 19 04:22etc
drwxrwxrwt.7 root root 4096 5月 19 04:22tmp>>> print(os.popen('ls -lt').readlines())
readlines()是以列表的形式打印出来
mands 模块(在Python2.X中纯在Python3中就移除了,在Python 3.X 中 被 sudprocess 取代,这里就不怎么介绍commands模块了)
使用commands模块的getoutput方法,这种方法同popend的区别在于popen返回的是一个类文件对象,而本方法将外部程序的输出结果当作字符串返回,很多情况下用起来要更方便些。
主要方法:
* commands.getstatusoutput(cmd)返回(status, output)
* commands.getoutput(cmd)只返回输出结果
* commands.getstatus(file) 返回ls -ld file的执行结果字符串,调用了getoutput,不建议使用此方法
3. subprocess 模块
官方文档:/3/library/subprocess.html
subprocess模块用于取代上面这些模块。ubprocess与system相比的优势是它更灵活(你可以得到标准输出,标准错误,“真正”的状态代码,更好的错误处理,等..)。我认为使用os.system已过时,或即将过时。
3.1 call 执行命令,返回状态码(命令正常执行返回0,报错则返回1)
1 >>> ret = subprocess.call('df -h', shell='True')2 Filesystem Size Used Avail Use%Mounted on3 /dev/mapper/VolGroup-lv_root4 18G 1.7G 15G 10% /
5 tmpfs 238M 0 238M 0% /dev/shm6 /dev/sda1 477M 38M 414M 9% /boot7
8 #两种不同的写法
9
10 >>> ret = subprocess.call(["ls", "-l"], shell=False) #shell为False的时候命令必须分开写
11 总用量 24
12 -rw-------. 1 root root 1068 8月 28 anaconda-ks.cfg13 -rw-r--r--. 1 root root 14484 8月 28 install.log14 -rw-r--r--. 1 root root 3482 8月 28 install.log.syslog
>>> print(ret)
0
3.2 check_call执行命令,如果执行成功则返回状态码0,否则抛异常
1 >>> ret = subprocess.check_call(['ls', '-l'], shell='False')2 anaconda-ks.cfg install.log install.log.syslog3 >>> print(ret)4 05
6 >>> ret = subprocess.check_call('ls -l', shell='True')7 总用量 24
8 -rw-------. 1 root root 1068 8月 28 anaconda-ks.cfg9 -rw-r--r--. 1 root root 14484 8月 28 install.log10 -rw-r--r--. 1 root root 3482 8月 28 install.log.syslog
3.3 check_output 执行命令,如果执行成功则返回执行结果,否则抛异常。
>>> subprocess.check_output(['echo', "Hello, Word"])
b'Hello, Word\n'
>>> subprocess.check_output('ls -l', shell='True')
b'\xe6\x80\xbb\xe7\x94\xa8\xe9\x87\x8f 24\n-rw-------. 1 root root 1068 8\xe6\x9c\x88 28 anaconda-ks.cfg\n-rw-r--r--. 1 root root 14484 8\xe6\x9c\x88 28 install.log\n-rw-r--r--. 1 root root 3482 8\xe6\x9c\x88 28 install.log.syslog\n'
返回结果为bays 类型, 不怎么常用这个
subprocess 模块 在Python3版本新加功能:(常用)
简要说明: 有需要用到python调用外部程序命令的同学们, 那么你们请一定选择subprocess库,它给我们工作带来极大的方便也许我这么解释不正确, 还是用官方的话来说吧 等这些。
subprocess.run()方法. 此方法作用: 使用参数运行命令并返回完整的进程实例
subprocess.run(*popenargs, input=None, timeout=None, check=False, **kwargs)
实例:
1 >>> subprocess.run(['ls', '-l']) # 注意 用[] 括号包着你要执行的命令,后面也可以跟路径 #相当于在系统中执行ls -l / 命令
2 总用量 24
3 -rw-------. 1 root root 1068 8月 28 anaconda-ks.cfg4 -rw-r--r--. 1 root root 14484 8月 28 install.log5 -rw-r--r--. 1 root root 3482 8月 28 install.log.syslog6 CompletedProcess(args=['ls', '-l'], returncode=0)7 >>> subprocess.run(['ls', '-l' , '/']) # 这是跟路径的 查看的是根下的8 总用量 98
9 dr-xr-xr-x. 2 root root 4096 8月 28 bin10 dr-xr-xr-x. 5 root root 1024 8月 29 boot11 drwxr-xr-x. 19 root root 3760 5月 20 04:06dev12 drwxr-xr-x. 78 root root 4096 5月 20 04:06etc13 drwxr-xr-x. 2 root root 4096 6月 28 home14 dr-xr-xr-x. 8 root root 4096 8月 29 lib15 dr-xr-xr-x. 9 root root 12288 4月 26 08:08lib6416 drwx------. 2 root root 16384 8月 28 lost+found
Popen
实际上,我们上面的三个函数都是基于Popen()的封装(wrapper)。这些封装的目的在于让我们容易使用子进程。当我们想要更个性化我们的需求的时候,就要转向Popen类,该类生成的对象用来代表子进程。
与上面的封装不同,Popen对象创建后,主程序不会自动等待子进程完成。我们必须调用对象的wait()方法,父进程才会等待 (也就是阻塞block):
[root@localhost opt]#vim 1.py#!/etc/svn/python
importsubprocessimportsubprocess
child= subprocess.Popen(["ping","-c","5","127.0.0.1"])print("parent 进程")
[root@localhost opt]#python3 1.py结果:
parent 进程 #父进程没有等子进程结束 直接执行的父进程 在执行的子进程
[root@localhost opt]#PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.023ms64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.030ms64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.030ms64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.030ms64 bytes from 127.0.0.1: icmp_seq=5 ttl=64 time=0.031ms--- 127.0.0.1 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4000ms
对于等待的情况:
1 importsubprocess2 child = subprocess.Popen(["ping","-c","5",""])3 child.wait()4 print("parent process")
此外,你还可以在父进程中对子进程进行其它操作,比如我们上面例子中的child对象:
child.poll()# 检查子进程状态
child.kill()# 终止子进程
child.wait() # 等待子进程结束
child.send_signal()# 向子进程发送信号
child.terminate() # 终止子进程
子进程的PID存储在child.pid
stdin标准输入, stdout 标准输出,stderr标准错误:
我们可以在Popen()建立子进程的时候改变标准输入、标准输出和标准错误,并可以利用subprocess.PIPE将多个子进程的输入和输出连接在一起,构成管道(pipe):
importsubprocess
a= subprocess.Popen(["ls","-l"], stdout=subprocess.PIPE)
b= subprocess.Popen(["wc"], stdin=a.stdout,stdout=subprocess.PIPE)
out=municate() # 是Popen对象的一个方法,该方法会阻塞父进程,直到子进程完成print(out)
结果:
[root@localhost opt]# python3 test.py
(b' 3 20 117\n', None)
subprocess.PIPE实际上为文本流提供一个缓存区。a的stdout将文本输出到缓存区,随后b的stdin从该PIPE中将文本读取走。b的输出文本也被存放在PIPE中,直到communicate()方法从PIPE中读取出PIPE中的文本。
要注意的是,communicate()是Popen对象的一个方法,该方法会阻塞父进程,直到子进程完成。
如果觉得《python中执行linux命令(调用linux命令)_常见Python中调用Linux命令》对你有帮助,请点赞、收藏,并留下你的观点哦!