Python执行系统命令的方法

os.system('cat /proc/cpuinfo')


output = os.popen('cat /proc/cpuinfo')


print output.read()


通过 os.popen() 返回的是 file read 的对象,对其进行读取 read() 的操作可以看到执行的输出。但是怎么读取程序执行的返回值呢。Google 给我指向了 commands — Utilities for running commands。


这样通过 commands.getstatusoutput() 一个方法就可以获得到返回值和输出,非常好用。


(status, output) = commands.getstatusoutput('cat /proc/cpuinfo')


print status, output


Python Document 中给的一个例子,很清楚的给出了各方法的返回。


>>> import commands


>>> commands.getstatusoutput('ls /bin/ls')


(0, '/bin/ls')


>>> commands.getstatusoutput('cat /bin/junk')


(256, 'cat: /bin/junk: No such file or directory')


>>> commands.getstatusoutput('/bin/junk')


(256, 'sh: /bin/junk: not found')


>>> commands.getoutput('ls /bin/ls')


'/bin/ls'
>>> commands.getstatus('/bin/ls')


'-rwxr-xr-x 1 root 13352 Oct 14 1994 /bin/ls'

cat /home/haoren/study-python/shuju.txt

170302-10:00:18 Bill[40268] TRACE: [人民币统计][通用人民币操作]用户扣除人民币,用户:56382627,人民币:19009423
170302-10:00:18 Bill[40268] TRACE: [人民币统计][通用人民币操作]用户扣除人民币,用户:56382627,人民币:19009323
170302-10:00:18 Bill[40268] TRACE: [人民币统计][通用人民币操作]用户扣除人民币,用户:53621808,人民币:13913410
170302-10:00:18 Bill[40268] TRACE: [人民币统计][通用人民币操作]用户扣除人民币,用户:57032579,人民币:9094648
170302-10:00:01 Bill[40268] INFO: [人民币结算]时间(1488420001),用户ID(41077113),原来人民币(59312),现在人民币(59112),人民币操作(2),扣除(200),操作类型(11),操作详情(0),操作数量(0).描述:连连购
170302-10:00:01 Bill[40268] INFO: [人民币结算]时间(1488420001),用户ID(41077113),原来人民币(59112),现在人民币(59012),人民币操作(2),扣除(100),操作类型(11),操作详情(0),操作数量(0).描述:连连购
170302-10:00:02 Bill[40268] INFO: [人民币结算]时间(1488420002),用户ID(31869180),原来人民币(6733),现在人民币(6633),人民币操作(2),扣除(100),操作类型(1),操作详情(80),操作数量(1).描述:送礼品
170302-10:00:11 Bill[40268] INFO: [人民币结算]时间(1488420011),用户ID(70461470),原来人民币(20453),现在人民币(20353),人民币操作(2),扣除(100),操作类型(11),操作详情(0),操作数量(0).描述:连连购
170302-10:00:11 Bill[40268] INFO: [人民币结算]时间(1488420011),用户ID(70461470),原来人民币(20353),现在人民币(20253),人民币操作(2),扣除(100),操作类型(11),操作详情(0),操作数量(0).描述:连连购
170302-10:00:11 Bill[40268] INFO: [人民币结算]时间(1488420011),用户ID(53537267),原来人民币(3380),现在人民币(3280),人民币操作(2),扣除(100),操作类型(11),操作详情(0),操作数量(0).描述:连连购

#!/usr/bin/python
#-*- coding:UTF-8 -*-
import calendar
import datetime
import MySQLdb
import os, sys, re,string
import time, tarfile,getopt


import random
import pwd
import spwd

import commands


list = []


dic = {}


os.system("cat /home/haoren/study-python/shuju.txt |grep 41077113 |awk -F '[()]' '{print $2}'")


output = os.popen('cat /home/haoren/study-python/shuju.txt |grep 41077113')

print output.read()


(status, output) = commands.getstatusoutput('cat /home/haoren/study-python/shuju.txt |grep 41077113')


print status
print output


执行结果

1488420001
1488420001
170302-10:00:01 Bill[40268] INFO: [人民币结算]时间(1488420001),用户ID(41077113),原来人民币(59312),现在人民币(59112),人民币操作(2),扣除(200),操作类型(11),操作详情(0),操作数量(0).描述:连连购
170302-10:00:01 Bill[40268] INFO: [人民币结算]时间(1488420001),用户ID(41077113),原来人民币(59112),现在人民币(59012),人民币操作(2),扣除(100),操作类型(11),操作详情(0),操作数量(0).描述:连连购


0
170302-10:00:01 Bill[40268] INFO: [人民币结算]时间(1488420001),用户ID(41077113),原来人民币(59312),现在人民币(59112),人民币操作(2),扣除(200),操作类型(11),操作详情(0),操作数量(0).描述:连连购
170302-10:00:01 Bill[40268] INFO: [人民币结算]时间(1488420001),用户ID(41077113),原来人民币(59112),现在人民币(59012),人民币操作(2),扣除(100),操作类型(11),操作详情(0),操作数量(0).描述:连连购


os.system(cmd)的返回值只会有0(成功),1,2


os.popen(cmd)会把执行的cmd的输出作为值返回。

Python调用Shell脚本,有两种方法:os.system(cmd)或os.popen(cmd),前者返回值是脚本的退出状态码,后者的返回值是脚本执行过程中的输出内容。实际使用时视需求情况而选择。
现假定有一个shell脚本test.sh:
#!/bin/bash
1. echo "hello world!"
2. exit 3


os.system(cmd):


该方法在调用完shell脚本后,返回一个16位的二进制数,低位为杀死所调用脚本的信号号码,高位为脚本的退出状态码,即脚本中“exit 1”的代码执行后,os.system函数返回值的高位数则是1,如果低位数是0的情况下,则函数的返回值是0×100,换算为10进制得到256。


如果我们需要获得os.system的正确返回值,那使用位移运算可以还原返回值:
1. >>> n = os.system(test.sh)
2. >>> n >> 8
3. >>> 3
os.popen(cmd):


这种调用方式是通过管道的方式来实现,函数返回一个file-like的对象,里面的内容是脚本输出的内容(可简单理解为echo输出的内容)。使用os.popen调用test.sh的情况:


python调用Shell脚本,有两种方法:os.system(cmd)或os.popen(cmd),前者返回值是脚本的退出状态码,后者的返回值是脚本执行过程中的输出内容。实际使用时视需求情况而选择。


明显地,像调用”ls”这样的shell命令,应该使用popen的方法来获得内容


以前就疑惑popen和system有什么不同,今天实际的应用,才让我恍然大悟


os.popen()可以实现一个“管道”,从这个命令获取的值可以继续被调用。而os.system不同,它只是调用,调用完后自身退出,可能返回个0吧


比如,我想得到ntpd的进程id,就要这么做:


os.popen('ps -C ntpd | grep -v CMD |awk '{ print $1 }').readlines()[0]


Python中执行系统命令常见方法有两种:


两者均需 import os

(1) os.system

# 仅仅在一个子终端运行系统命令,而不能获取命令执行后的返回信息

system(command) -> exit_status
Execute the command (a string) in a subshell.

# 如果再命令行下执行,结果直接打印出来

1 >>> os.system('ls')
2 04101419778.CHM bash document media py-django video
3 11.wmv books downloads Pictures python
4 all-20061022 Desktop Examples project tools
(2) os.popen

# 该方法不但执行命令还返回执行后的信息对象

popen(command [, mode='r' [, bufsize]]) -> pipe
Open a pipe to/from a command returning a file object.

例如:

01 >>>tmp = os.popen('ls *.py').readlines()
02 >>>tmp
03 Out[21]:
04 ['dump_db_pickle.py ',
05 'dump_db_pickle_recs.py ',
06 'dump_db_shelve.py ',
07 'initdata.py ',
08 '__init__.py ',
09 'make_db_pickle.py ',
10 'make_db_pickle_recs.py ',
11 'make_db_shelve.py ',
12 'peopleinteract_query.py ',
13 'reader.py ',
14 'testargv.py ',
15 'teststreams.py ',
16 'update_db_pickle.py ',
17 'writer.py ']
好处在于:将返回的结果赋于一变量,便于程序的处理。

(3) 使用模块subprocess

1 >>> import subprocess
2 >>> subprocess.call (["cmd", "arg1", "arg2"],shell=True)
获取返回和输出:

1 import subprocess
2 p = subprocess.Popen('ls', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
3 for line in p.stdout.readlines():
4 print line,
5 retval = p.wait()
(4) 使用模块commands模块

1 >>> import commands
2 >>> dir(commands)
3 ['__all__', '__builtins__', '__doc__', '__file__', '__name__', 'getoutput', 'getstatus','getstatusoutput', 'mk2arg', 'mkarg']
4 >>> commands.getoutput("date")
5 'Wed Jun 10 19:39:57 CST 2009'
6 >>>
7 >>> commands.getstatusoutput("date")
8 (0, 'Wed Jun 10 19:40:41 CST 2009')


注意: 当执行命令的参数或者返回中包含了中文文字,那么建议使用subprocess,如果使用os.popen则会出现下面的错误:

查看源代码打印帮助
1 Traceback (most recent call last):
2 File "./test1.py", line 56, in
3 main()
4 File "./test1.py", line 45, in main
5 fax.sendFax()
6 File "./mailfax/Fax.py", line 13, in sendFax
7 os.popen(cmd)
8 UnicodeEncodeError: 'ascii' codec can't encode characters in position 46-52: ordinal not inrange(128)

1.os.system()    执行操作系统的命令,将结果输出到屏幕,只返回命令执行状态(0:成功,非 0 : 失败)


import os
>>> a = os.system("df -Th")
Filesystem Type Size Used Avail Use% Mounted on
/dev/sda3 ext4 1.8T 436G 1.3T 26% /
tmpfs tmpfs 16G 0 16G 0% /dev/shm
/dev/sda1 ext4 190M 118M 63M 66% /boot
>>> a
0 # 0 表示执行成功


# 执行错误的命令
>>> res = os.system("list")
sh: list: command not found
>>> res
32512 # 返回非 0 表示执行错误

2. os.popen()  执行操作系统的命令,会将结果保存在内存当中,可以用read()方法读取出来


import os
>>> res = os.popen("ls -l")
# 将结果保存到内存中
>>> print res
<open file 'ls -l', mode 'r' at 0x7f02d249c390>
# 用read()读取内容
>>> print res.read()
total 267508
-rw-r--r-- 1 root root 260968 Jan 27 2016 AliIM.exe
-rw-------. 1 root root 1047 May 23 2016 anaconda-ks.cfg
-rw-r--r-- 1 root root 9130958 Nov 18 2015 apache-tomcat-8.0.28.tar.gz
-rw-r--r-- 1 root root 0 Oct 31 2016 badblocks.log
drwxr-xr-x 5 root root 4096 Jul 27 2016 certs-build
drwxr-xr-x 2 root root 4096 Jul 5 16:54 Desktop
-rw-r--r-- 1 root root 2462 Apr 20 11:50 Face_24px.ico

三、subprocess模块

1、subprocess.run()

>>> import subprocess
# python 解析则传入命令的每个参数的列表
>>> subprocess.run(["df","-h"])


Filesystem Size Used Avail Use% Mounted on
/dev/mapper/VolGroup-LogVol00
289G 70G 204G 26% /
tmpfs 64G 0 64G 0% /dev/shm
/dev/sda1 283M 27M 241M 11% /boot
CompletedProcess(args=['df', '-h'], returncode=0)
# 需要交给Linux shell自己解析,则:传入命令字符串,shell=True
>>> subprocess.run("df -h|grep /dev/sda1",shell=True)


/dev/sda1 283M 27M 241M 11% /boot
CompletedProcess(args='df -h|grep /dev/sda1', returncode=0)

2、subprocess.call()  执行命令,返回命令的结果和执行状态,0或者非0

  

>>> res = subprocess.call(["ls","-l"])
总用量 28
-rw-r--r-- 1 root root 0 6月 16 10:28 1
drwxr-xr-x 2 root root 4096 6月 22 17:48 _1748
-rw-------. 1 root root 1264 4月 28 20:51 anaconda-ks.cfg
drwxr-xr-x 2 root root 4096 5月 25 14:45 monitor
-rw-r--r-- 1 root root 13160 5月 9 13:36 npm-debug.log
# 命令执行状态
>>> res
0

3、subprocess.check_call()  执行命令,返回结果和状态,正常为0 ,执行错误则抛出异常


>>> subprocess.check_call(["ls","-l"])
总用量 28
-rw-r--r-- 1 root root 0 6月 16 10:28 1
drwxr-xr-x 2 root root 4096 6月 22 17:48 _1748
-rw-------. 1 root root 1264 4月 28 20:51 anaconda-ks.cfg
drwxr-xr-x 2 root root 4096 5月 25 14:45 monitor
-rw-r--r-- 1 root root 13160 5月 9 13:36 npm-debug.log
0
>>> subprocess.check_call(["lm","-l"])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib64/python2.7/subprocess.py", line 537, in check_call
retcode = call(*popenargs, **kwargs)
File "/usr/lib64/python2.7/subprocess.py", line 524, in call
return Popen(*popenargs, **kwargs).wait()
File "/usr/lib64/python2.7/subprocess.py", line 711, in __init__
errread, errwrite)
File "/usr/lib64/python2.7/subprocess.py", line 1327, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory

4、subprocess.getstatusoutput()  接受字符串形式的命令,返回 一个元组形式的结果,第一个元素是命令执行状态,第二个为执行结果


#执行正确
>>> subprocess.getstatusoutput('pwd')
(0, '/root')
#执行错误
>>> subprocess.getstatusoutput('pd')
(127, '/bin/sh: pd: command not found')

5、subprocess.getoutput() 接受字符串形式的命令,放回执行结果


>>> subprocess.getoutput('pwd')
'/root'

6、subprocess.check_output()  执行命令,返回执行的结果,而不是打印


>>> res = subprocess.check_output("pwd")
>>> res
b'/root ' # 结果以字节形式返回

原文地址:https://www.cnblogs.com/chengxuyonghu/p/13601965.html