0%

一、概要

在class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑,对于每一个类的成员(属性,字段,方法)的修饰符有两种

  • 公开成员,在任何地方都能访问,即可在类外面和对象调用方法进行访问;
  • 私有成员,只有在类的内部才能访问;
Read more »

一、字段

1、概念

字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同。字段名一般是名词

Read more »

安装配置

一、概要

目前,Python有两个版本,一个是2.x 版,一个是3.x 版,这两个版本 是不兼容的。由于 3.x 版越来越普及,我们的课程将以最新的 Python 3.6 版本为基础。

Read more »

面向对象

一、简介

面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用

Read more »

错误与异常

一、概要

​ 一个程序即使没有任何语法错误,即使解题的逻辑也正确,在执行的时候仍然可能出现 各种“运行时错误”,导致程序无法按照预定的步骤顺利执行、正常结束。其后果是要么由系 统强行中止程序的运行,要么程序带着错误继续运行而得出错误的结果。这类运行时错误称 为异常或例外(exception)。产生异常的原因是复杂而多样的,既有程序设计的问题,也有运行环境的问题,如除数为零、用户输入数据的类型或个数不对、列表索引越界,写入文件的时候,磁盘满了,或者从网络抓取数据,网络突然断掉了等等。

Read more »

一、概要

python中的time,datetime提供了简单和复杂的方式操作日期和时间的类。虽然支持日期和时间算法,但我们的学习的重点是获取日期和时间,用于输出格式和操作

Python 提供了一个 datetime 和 calendar 模块可以用于格式化日期和时间。

Read more »

os模块操作系统数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
获取工作路径:
os.getcwd()

<!-- more -->
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

创建目录:
语法:
os.mkdir(path[, mode])
注意:可选项mode为权限设置,默认权限为0755,但是g和o位置的写权限是设置不上的

os.mkdir("/python/test",0755)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

创建空文件:
os.mknod("/tmp/test.txt",0666)
注意:同样权限为可选项,而且也不能设置g和o位置的写权限

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

创建连级目录:
os.makedirs('/tmp/bb/cc/dd/ee',0111)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

列出指定目录下文件:
os.listdir("/python")

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

查看文件状态:
os.stat("/python")

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

重命名文件:
os.rename("/python/test1","/python/test5")

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

删除空目录
os.rmdir("/python/test")

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

删除非空目录:
需要导入shutil模块
shutil.rmtree("/tmp/aa")

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

切换路径 :
os.chdir("/")

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

判断文件或目录是否存在:
os.path.exist()

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

判断文件权限:
概述:
os.access() 方法使用当前的uid/gid(只对当前用户的权限生效)尝试访问路径。大部分操作
使用有效的 uid/gid, 因此运行环境可以在 suid/sgid 环境尝试。

语法:
os.access(path, mode);

参数:
path -- 要用来检测是否有访问权限的路径。
mode -- mode为F_OK,测试存在的路径,或者它可以是包含R_OK, W_OK和X_OK或者R_OK, W_OK和X_OK其中之一

os.F_OK: 作为access()的mode参数,测试path是否存在。
os.R_OK: 包含在access()的mode参数中 , 测试path是否可读。
os.W_OK: 包含在access()的mode参数中 , 测试path是否可写。
os.X_OK: 包含在access()的mode参数中 ,测试path是否可执行。

返回值:
如果允许访问返回 True , 否则返回False。

实例:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os, sys
# 假定 /tmp/foo.txt 文件存在,并有读写权限
ret = os.access("/tmp/foo.txt", os.F_OK)
print "F_OK - 返回值 %s"% ret

ret = os.access("/tmp/foo.txt", os.R_OK)
print "R_OK - 返回值 %s"% ret

ret = os.access("/tmp/foo.txt", os.W_OK)
print "W_OK - 返回值 %s"% ret

ret = os.access("/tmp/foo.txt", os.X_OK)
print "X_OK - 返回值 %s"% ret

执行以上程序输出结果为:
F_OK - 返回值 True
R_OK - 返回值 True
W_OK - 返回值 True
X_OK - 返回值 False

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
更改文件或目录的权限:
语法
os.chmod(path, mode)

参数
path -- 文件名路径或目录路径。
flags -- 可用以下选项按位或操作生成, 目录的读权限表示可以获取目录里文件名列表, ,执行权限表示可
以把工作目录切换到此目录 ,删除添加目录里的文件必须同时有写和执行权限 ,文件权限以用户id->组id-
>其它顺序检验,最先匹配的允许或禁止权限被应用。
stat.S_IXOTH: 其他用户有执行权0o001
stat.S_IWOTH: 其他用户有写权限0o002
stat.S_IROTH: 其他用户有读权限0o004
stat.S_IRWXO: 其他用户有全部权限(权限掩码)0o007
stat.S_IXGRP: 组用户有执行权限0o010
stat.S_IWGRP: 组用户有写权限0o020
stat.S_IRGRP: 组用户有读权限0o040
stat.S_IRWXG: 组用户有全部权限(权限掩码)0o070
stat.S_IXUSR: 拥有者具有执行权限0o100
stat.S_IWUSR: 拥有者具有写权限0o200
stat.S_IRUSR: 拥有者具有读权限0o400
stat.S_IRWXU: 拥有者有全部权限(权限掩码)0o700
stat.S_ISVTX: 目录里文件目录只有拥有者才可删除更改0o1000
stat.S_ISGID: 执行此文件其进程有效组为文件所在组0o2000
stat.S_ISUID: 执行此文件其进程有效用户为文件所有者0o4000
stat.S_IREAD: windows下设为只读
stat.S_IWRITE: windows下取消只读

返回值
该方法没有返回值。

实例
以下实例演示了 chmod() 方法的使用:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os, sys, stat
# 假定 /tmp/foo.txt 文件存在,设置文件可以通过用户组执行

os.chmod("/tmp/foo.txt", stat.S_IXGRP)

# 设置文件可以被其他用户写入
os.chmod("/tmp/foo.txt", stat.S_IWOTH)

print "修改成功!!"
执行以上程序输出结果为:
修改成功!!

注意:不一定用stat模块的权限状态,可以直接使用数字权限,os.chmod('a.txt',0777)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
创建硬链接
该方法对于创建一个已存在文件的拷贝是非常有用的。

语法:
os.link(src, dst)

参数
src -- 用于创建硬连接的源地址
dst -- 用于创建硬连接的目标地址

返回值
该方法没有返回值。

实例
#!/usr/bin/python
# -*- coding: UTF-8 -*-

import os, sys

# 打开文件
path = "/var/www/html/foo.txt"
fd = os.open( path, os.O_RDWR|os.O_CREAT )

# 关闭文件
os.close( fd )

# 创建以上文件的拷贝
dst = "/tmp/foo.txt"
os.link( path, dst)

print "创建硬链接成功!!"
执行以上程序输出结果为:
创建硬链接成功!!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
打开一个文件:
打开一个文件,并且设置需要的打开选项,模式参数mode参数是可选的,默认为 0777。

语法
open()方法语法格式如下:
os.open(file, flags[, mode]);

参数:
file -- 要打开的文件
flags -- 该参数可以是以下选项,多个使用 "|" 隔开:

os.O_RDONLY: 以只读的方式打开
os.O_WRONLY: 以只写的方式打开
os.O_RDWR : 以读写的方式打开
os.O_NONBLOCK: 打开时不阻塞
os.O_APPEND: 以追加的方式打开
os.O_CREAT: 创建并打开一个新文件
os.O_TRUNC: 打开一个文件并截断它的长度为零(必须有写权限)
os.O_EXCL: 如果指定的文件存在,返回错误
os.O_SHLOCK: 自动获取共享锁
os.O_EXLOCK: 自动获取独立锁
os.O_DIRECT: 消除或减少缓存效果
os.O_FSYNC : 同步写入
os.O_NOFOLLOW: 不追踪软链接
mode -- 类似 chmod()。

返回值:
返回新打开文件的描述符。

实例:
#!/usr/bin/python
# -*- coding: UTF-8 -*-

import os, sys

# 打开文件
fd = os.open( "foo.txt", os.O_RDWR|os.O_CREAT )

# 写入字符串
os.write(fd, "This is test")

# 关闭文件
os.close( fd )

print "关闭文件成功!!"
执行以上程序输出结果为:
关闭文件成功!!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#!/usr/bin/env python
#coding=utf-8
import os
dir = "/python/test2"
print os.getcwd() #获取工作路径

os.mkdir("/python/test1") #创建目录
os.mkdir(dir)
os.mknod("/tmp/a.txt") #创建空文件
os.makedirs("/python/test11/a/b/c") #创建连级目录

print os.listdir("/python") #列出指定目录下文件

print os.stat("/python") #类似于系统命令stat

os.rename("/python/test1","/python/test5") #重命名文件

os.rmdir("/python/test") #删除目录

=============================

#!/usr/bin/env python
import os
os.chdir("/") #切换路径
pwd = os.getcwd()
print os.listdir(pwd)
=============================


path方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
os.path.exist() #判断文件或目录是否存在

os.path.按tab键 查看os.path内所有方法,大多都很有用

os.path模块常用函数简介
basename() #去掉目录路径,返回文件名
>>>os.path.basename("/root/python/zip.py")
'zip.py'

dirname() #去掉文件名,返回目录路径
>>> os.path.dirname("/root/python/zip.py")
'/root/python'

join() #将分离的各部分组合成一个路径名
>>> os.path.join("/root/python/","zip.py")
'/root/python/zip.py'

split() #返回目录路径和文件名的元组
>>> os.path.split("/root/python/zip.py")
('/root/python', 'zip.py')

splitdrive() #返回驱动符号和路径字符元组
>>> os.path.splitdrive("/root/python/zip.py")
('', '/root/python/zip.py')

splitext() #返回文件名和扩展名元组
>>>os.path.splitext("zip.py")
('zip','.py')

getatime() #返回文件最近的访问时间
>>> os.path.getatime("/root/python/zip.py")
1297653596
>>> time.ctime(1297653596)
'Mon Feb 14 11:19:56 2011'

getctime() #返回文件的创建时间

getmtime() #返回文件的修改时间

getsize() #返回文件的大小单位为字节
>>> os.path.getsize("zip.py")
864

exists() #指定路径(文件或目录)是否存在
>>> os.path.exists("/root/python/xukai.py")
False
>>> os.path.exists("/root/python/zip.py")
True

isabs() #指定路径是否为绝对路径
>>> os.path.isabs("/root/python/zip.py")
True
>>> os.path.isabs("root/python/zip.py")
False

isdir() #指定路径是否存在且为一个目录

isfile() #指定的路径是否为一个文件

samefile() #两个路径名是否指向同一个文件

跨平台

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
路径分隔符(POSIX 使用 "/", DOS 和 Windows 使用 "\", 旧版本的 MacOS 使用":"), 它用来
分隔文件路径名, 标记当前目录和父目录.
当我们创建要跨这三个平台的应用的时候, 这些差异会让我们感觉非常麻烦(而且支持的平台越多越麻烦)
Python 的 os 模块设计者已经帮我们想到了这些问题.
os 模块有五个很有用的属性:
linesep 用于在文件中分隔行的字符串
sep 用来分隔文件路径名的字符串
pathsep用于分隔文件路径的字符串
curdir 当前工作目录的字符串名称
pardir (当前工作目录的)父目录字符串名称
不管你使用的是什么平台, 只要你导入了 os 模块, 这些变量自动会被设置为正确的值, 减少了你的麻烦

下例中我们每次从用户接收一行输入, 然后将文本保存到文件中. 由于 raw_input()不会保留用户输入的换行符 , 调用write()方法时必须加上 换行符。而且 ,在键盘上很难输入一个EOF(end-of-file)字符,所以,程序使用句号( . )作为文件结束的标志, 当用户输入句号后会自动结束输入并关闭文件.

import os
filename = raw_input('Enter file name: ')
fobj = open(filename, 'w')
while True:
aLine = raw_input("Enter a line ('.' to quit): ")
if aLine != ".":
fobj.write('%s%s' % (aLine, os.linesep) #这里的linesep不管是windows还是linux都可以表示他们的换行符
else:
break
fobj.close()

statsvfs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
python获得磁盘剩余空间statvfs:

>>> import os
>>> import statvfs
>>> vfs=os.statvfs("/home")
>>> vfs
(4096, 4096, 70959944, 70058799, 66396080, 73269248, 73234981, 73234981, 0, 255)
>>> dir(statvfs)
['F_BAVAIL', 'F_BFREE', 'F_BLOCKS', 'F_BSIZE', 'F_FAVAIL', 'F_FFREE', 'F_FILES', 'F_FLAG

struct statfs {
long f_type; /* 文件系统类型 */
long f_bsize; /* 经过优化的传输块大小 */
long f_blocks; /* 文件系统数据块总数 */
long f_bfree; /* 可用块数 */
long f_bavail; /* 非超级用户可获取的块数 */
long f_files; /* 文件结点总数 */
long f_ffree; /* 可用文件结点数 */
fsid_t f_fsid; /* 文件系统标识 */
long f_namelen; /* 文件名的最大长度 */
};
statfs结构中可用空间块数有两种f_bfree和 f_bavail,前者是硬盘所有剩余空间,后者为非root用
户剩余空间,ext3文件系统给root用户分有5%的独享空间,所以这里是不同的地方。这里要强调的
是每块的大小一般是4K。因此,要实现与df结果一致的就得在获得块数上乘以4,这样已用、可用、
总块数就可以实现。如果还要实现百分比一致,那么要注意的是,df命令获得是整数百分比,没有小
数,这里使用的进一法,而不是四舍五入法。所以在程序里直接+1取整。

def disk_stat():
import os
disk = os.statvfs('/usr')
percent = (disk.f_blocks - disk.f_bfree) * 100 / (disk.f_blocks -disk.f_bfree + disk.f_bavail) + 1
return percent
print disk_stat()

获得df多个磁盘空间及内存:
#!/usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import division
import os
file = open('/soft/disk','a')

def disk_root():
disk = os.statvfs('/')
percent = (disk.f_blocks - disk.f_bfree) * 100 / (disk.f_blocks -disk.f_bfree + disk.f_bavail)
return percent

def disk_backup():
disk = os.statvfs('/backup')
percent = (disk.f_blocks - disk.f_bfree) * 100 / (disk.f_blocks -disk.f_bfree + disk.f_bavail)
return percent

def disk_project():
disk = os.statvfs('/project')
percent = (disk.f_blocks - disk.f_bfree) * 100 / (disk.f_blocks -disk.f_bfree + disk.f_bavail)
return percent

def mem_stat():
mem = {}
f = open('/proc/meminfo')
lines = f.readlines()
f.close()
for line in lines:
name = line.split(':')[0]
var = line.split(':')[1].split()[0]
mem[name] = long(var)
Mem = (100 - ((mem['MemFree'] + mem['Buffers'] + mem['Cached']) / mem['MemTotal']) * 100)
return Mem

root = '/ %0.f%%'%disk_root()+'\n'
backup = '/backup %0.f%%'%disk_backup()+'\n'
project = '/project %0.f%%'%disk_project()+'\n'
memory = 'memory %0.2f%%'%mem_stat()+'\n'

file.writelines('Filesystem&Mem Use%'+'\n'+'-----------------------'+'\n')
file.writelines(root)
file.writelines(backup)
file.writelines(project)
file.writelines(memory)
file.flush()
file.close()

打印结果:
cat disk
Filesystem&Mem Use%
-----------------------
/ 24%
/backup 62%
/project 21%
memory 26.33%


监控磁盘使用率

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
Python实现的监测服务器硬盘使用率
此脚本主要用于zabbix监控系统硬盘只用,适用于windows和linux系统,返回值为0为正常,有几个分区的硬盘剩余少于10G或
低于10%就为报警阀值(windows的C盘和linux的根分区除外):
import platform
import commands

def w_disk():
import wmi
c = wmi.WMI ()
i = 0
for disk in c.Win32_LogicalDisk (DriveType=3):
a = int(disk.FreeSpace) / (1024*1024*1024)
b = int(100.0 * long (disk.FreeSpace) / long (disk.Size))
if disk.Caption == "C:":
if (a < 2) or (b < 10):
i += 1
else:
i += 0
else:
if (a < 10) or (b < 10):
i += 1
else:
i += 0
print i

def L_disk():
free = commands.getstatusoutput('df -h|grep dev|egrep -v "tmp|var|shm"')
list = free[1].split('\n')
i = 0
for disk in range(len(list)):
vd = list[disk][6:8]
a = list[disk].split()[3]
if a[-1] == 'T':
a = int(float(a[:-1]))*1024
else:
a = int(float(a[:-1]))
b = 100 - int(list[disk].split()[4][:-1])
if vd == "da":
if (a < 2) or (b < 10):
i += 1
else:
i += 0
else:
if (a < 10) or (b < 10):
i += 1
else:
i += 0
print i

if __name__ == "__main__":
os = platform.system()
if os == "Windows":
w_disk()
elif os == "Linux":
L_disk()

python脚本监控Linux磁盘空间使用率

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#cat check_snmp_storage.py
#_*_ coding: utf-8 _*_

from sys import argv,exit
from decimal import Decimal
from optparse import OptionParser
from netsnmp import snmpwalk

parser = OptionParser('%prog -C -H -d -w -c ')

parser.add_option('-H', '--HostAddr', action='store', dest='hostaddress', help='Specify HostAddress')
parser.add_option('-C', '--community', action='store', dest='community', help='Specify host community')
parser.add_option('-d', '--device', action='store', dest='device', help='Specify a device')
parser.add_option('-w', '--warning', action='store', dest='warning', help='set the warning value')
parser.add_option('-c', '--critical', action='store', dest='critical', help='set the critical value')

(options, argvs) = parser.parse_args(argv)

desc_list = ['hrStorageDescr', 'hrStorageSize', 'hrStorageUsed', 'hrStorageAllocationUnits']

#依次获取desc_list对应的返回值,并分别存入列表
try:
for mibdsc in desc_list:
r1 = list(snmpwalk(mibdsc,Version=2,Community=options.community,DestHost=options.hostaddress))
if mibdsc == 'hrStorageDescr':
dev = r1
elif mibdsc == 'hrStorageSize':
size = r1
elif mibdsc == 'hrStorageUsed':
used = r1
elif mibdsc == 'hrStorageAllocationUnits':
units = r1
except TypeError:
parser.print_help()
exit(3)

size_list = {}
used_list = {}
per_list = {}
for devname in dev:
l = dev.index(devname) #依次获取该元素在列表的位置
dev_size = int(size[l]) * int(units[l]) / 1024 / 1024 #将磁盘容量单位转为M
dev_used = int(used[l]) * int(units[l]) / 1024 / 1024
used_percent = round(float(dev_used) / float(dev_size),2) * 100

size_list[devname] = dev_size
used_list[devname] = dev_used
per_list[devname] = used_percent

if float(options.warning) > float(options.critical):
print "-w <阀值> 必须等于或小于 -c <阀值>"
exit(3)
try:
if float(per_list[options.device]) < float(options.warning):
print 'OK - "%s" 使用了:%s%% | 总容量:%s MB,已使用:%s MB (w:%s%%, c:%s%%)' % (options.device, per_list[options.device], size_list[options.device], used_list[options.device], options.warning, options.critical)
exit(0)
elif float(options.critical) > float(per_list[options.device]) >= float(options.warning):
print 'Warning - "%s" 使用了:%s%% | 总容量:%s MB , 已使用:%s MB (w:%s%%, c:%s%%)' % (options.device, per_list[options.device], size_list[options.device], used_list[options.device], options.warning, options.critical)
exit(1)
elif float(per_list[options.device]) >= float(options.critical):
print 'Critical - "%s" 使用了:%s%% | 总容量:%s MB , 已使用:%s MB (w:%s%%, c:%s%%)' % (options.device, per_list[options.device], size_list[options.device], used_list[options.device], options.warning, options.critical)
exit(2)
except KeyError:
print '无响应或指定的文件系统不存在'
exit(3)

将脚本check_snmp_storage.py放到/usr/local/nagios/libexec目录下,给执行权限。直接执行脚本可以看到脚本的用法:

#python check_snmp_storage.py -h
usage: check_snmp_storage.py -C -H -d -w -c

options:
-h, --help show this help message and exit
-H HOSTADDRESS, --HostAddr=HOSTADDRESS
Specify HostAddress
-C COMMUNITY, --community=COMMUNITY
Specify host community
-d DEVICE, --device=DEVICE
Specify a device
-w WARNING, --warning=WARNING
set the warning value
-c CRITICAL, --critical=CRITICAL
set the critical value


commands.cfg配置如下:
define command{
command_name check_snmp_storage
command_line $USER1$/check_snmp_storage.py $ARG1$ -H $HOSTADDRESS$ $ARG2$ $ARG3$ $ARG4$

}

services.cfg配置如下:
define service{
use service02
host_name test
service_description /data
check_command check_snmp_storage!-C public!-d /data!-w 85!-c 90
}

Python获取CPU使用率、内存使用率、网络使用状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
注:需要安装psutil库
import sys
import os

import atexit
import time
import psutil

#print "Welcome,current system is",os.name," 3 seconds late start to get data..."
time.sleep(3)

line_num = 1

#function of Get CPU State;
def getCPUstate(interval=1):
return (" CPU: " + str(psutil.cpu_percent(interval)) + "%")
#function of Get Memory
def getMemorystate():
phymem = psutil.virtual_memory()
line = "Memory: %5s%% %6s/%s"%(
phymem.percent,
str(int(phymem.used/1024/1024))+"M",
str(int(phymem.total/1024/1024))+"M"
)
return line
def bytes2human(n):
"""
>>> bytes2human(10000)
'9.8 K'
>>> bytes2human(100001221)
'95.4 M'
"""
symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
prefix = {}
for i, s in enumerate(symbols):
prefix[s] = 1 << (i+1)*10
for s in reversed(symbols):
if n >= prefix[s]:
value = float(n) / prefix[s]
return '%.2f %s' % (value, s)
return '%.2f B' % (n)


def poll(interval):
"""Retrieve raw stats within an interval window."""
tot_before = psutil.net_io_counters()
pnic_before = psutil.net_io_counters(pernic=True)
# sleep some time
time.sleep(interval)
tot_after = psutil.net_io_counters()
pnic_after = psutil.net_io_counters(pernic=True)
# get cpu state
cpu_state = getCPUstate(interval)
# get memory
memory_state = getMemorystate()
return (tot_before, tot_after, pnic_before, pnic_after,cpu_state,memory_state)

def refresh_window(tot_before, tot_after, pnic_before, pnic_after,cpu_state,memory_state):
if os.name == 'nt':
os.system("cls")
else:
os.system("clear")
"""Print stats on screen."""


#print current time #cpu state #memory
print(time.asctime()+" | "+cpu_state+" | "+memory_state)

# totals
print(" NetStates:")
print("total bytes: sent: %-10s received: %s" % (bytes2human(tot_after.bytes_sent),
bytes2human(tot_after.bytes_recv))
)
print("total packets: sent: %-10s received: %s" % (tot_after.packets_sent,
tot_after.packets_recv)
)
# per-network interface details: let's sort network interfaces so
# that the ones which generated more traffic are shown first
print("")
nic_names = pnic_after.keys()
#nic_names.sort(key=lambda x: sum(pnic_after[x]), reverse=True)
for name in nic_names:
stats_before = pnic_before[name]
stats_after = pnic_after[name]
templ = "%-15s %15s %15s"
print(templ % (name, "TOTAL", "PER-SEC"))
print(templ % (
"bytes-sent",
bytes2human(stats_after.bytes_sent),
bytes2human(stats_after.bytes_sent - stats_before.bytes_sent) + '/s',
))
print(templ % (
"bytes-recv",
bytes2human(stats_after.bytes_recv),
bytes2human(stats_after.bytes_recv - stats_before.bytes_recv) + '/s',
))
print(templ % (
"pkts-sent",
stats_after.packets_sent,
stats_after.packets_sent - stats_before.packets_sent,
))
print(templ % (
"pkts-recv",
stats_after.packets_recv,
stats_after.packets_recv - stats_before.packets_recv,
))
print("")

try:
interval = 0
while 1:
args = poll(interval)
refresh_window(*args)
interval = 1
except (KeyboardInterrupt, SystemExit):
pass

获取文件夹大小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
获取文件夹大小

import os
from os.path import join, getsize

def getdirsize(dir):
size = 0L
for root, dirs, files in os.walk(dir):
size += sum([getsize(join(root, name)) for name in files])
return size

if '__name__' == '__main__':
filesize = getdirsize(r'c:\windows')
print 'There are %.3f' % (size/1024/1024), 'Mbytes in c:\\windows'


[x+1 for x in range(10)]

sys模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
  sys.argv              命令行参数List,第一个元素是程序本身路径 
  sys.modules.keys() 返回所有已经导入的模块列表
  sys.exc_info() 获取当前正在处理的异常类,exc_type、exc_value、exc_traceback当前处理的异常详细信息
  sys.exit(n) 退出程序,正常退出时exit(0)
  sys.hexversion 获取Python解释程序的版本值,16进制格式如:0x020403F0
  sys.version 获取Python解释程序的版本信息
  sys.maxint 最大的Int值
  sys.maxunicode 最大的Unicode值
  sys.modules 返回系统导入的模块字段,key是模块名,value是模块
  sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
  sys.platform 返回操作系统平台名称
  sys.stdout 标准输出
  sys.stdin 标准输入
  sys.stderr 错误输出
  sys.exc_clear() 用来清除当前线程所出现的当前的或最近的错误信息
  sys.exec_prefix 返回平台独立的python文件安装的位置
  sys.byteorder 本地字节规则的指示器,big-endian平台的值是'big',little-endian平台的值是'little'
  sys.copyright 记录python版权相关的东西
  sys.api_version 解释器的C的API版本
  sys.version_info
  sys.displayhook(value) 如果value非空,这个函数会把他输出到sys.stdout,并且将他保存进__builtin__._.指在python的交互式解释器里,'_'代表上次你输入得到的结果,hook是钩子的意思,将上次的结果钩过来
  sys.getdefaultencoding() 返回当前你所用的默认的字符编码格式
  sys.getfilesystemencoding() 返回将Unicode文件名转换成系统文件名的编码的名字
  sys.setdefaultencoding(name) 用来设置当前默认的字符编码,如果name和任何一个可用的编码都不匹配,抛出LookupError,这个函数只会被site模块的sitecustomize使用,一旦被site模块使用了,他会从sys模块移除
  sys.builtin_module_names Python解释器导入的模块列表
  sys.executable Python解释程序路径
  sys.getwindowsversion() 获取Windows的版本
  sys.stdin.readline() 从标准输入读一行,sys.stdout.write("a") 屏幕输出a

python之sys模块详解

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sys.argv:
实现从程序外部向程序传递参数。
示例:sys.py
#!/usr/bin/env python
import sys
print sys.argv[0]
print sys.argv[1]
运行:
# python sys.py argv1
sys.py
argv1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sys.exit([arg]):
功能:执行到主程序末尾,解释器自动退出,但是如果需要中途退出程序,可以调用sys.exit函数,带有
一个可选的整数参数返回给调用它的程序,表示你可以在主程序中捕获对sys.exit的调用。(0是正常退
出,其他(1-127)为异常)

例:exit.py
#!/usr/bin/env python
import sys
def exitfunc(value):
print value
sys.exit(0)

print "hello"

try:
sys.exit(1)
except SystemExit,value:
exitfunc(value)

print "come"

运行:
# python exit.py
hello
1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sys.path
获取指定模块搜索路径的字符串集合,可以将写好的模块放在得到的某个路径下,就可以在程序中import时
正确找到。
例:
>>> import sys
>>> sys.path
['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/
usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-
packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PILcompat', '/
usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/python2.7/dist-packages/ubuntu-sso-client']

有时候为了让python能够找到我们自己定义的模块,需要修改sys.path的内容,比如:

# 在path的开始位置插入test
>>> sys.path.insert(0,'test')
>>> sys.path
['test', '', 'E:\\Python27\\Lib\\idlelib', 'C:\\Windows\\system32\\python27.zip', 'E:\\Python27\
\DLLs', 'E:\\Python27\\lib', 'E:\\Python27\\lib\\plat-win', 'E:\\Python27\\lib\\lib-tk', 'E:\
\Python27', 'E:\\Python27\\lib\\site-packages']

# 可以成功import test
>>> import test

# 找不到 other 这个模块
>>> import other
Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
import other
ImportError: No module named other

# 需要添加path
>>> sys.path.insert(0,'other')
>>> import other

也可以用sys.path.append(“mine module path”)来添加自定义的module。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sys.platform
获取当前执行环境的平台,如win32表示是Windows 32bit操作系统,linux2表示是linux平台
# linux
>>> import sys
>>> sys.platform
'linux2'

# windows
>>> import sys
>>> sys.platform
'win32'
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

sys.stdin,sys.stdout,sys.stderr:
stdin , stdout , 以及stderr 变量包含与标准I/O 流对应的流对象. 如果需要更好地控制输出,而print不能满
足你的要求, 它们就是你所需要的. 你也可以替换它们, 这时候你就可以重定向输出和输入到其它设备
( device ), 或者以非标准的方式处理它们

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sys.modules
功能:sys.modules是一个全局字典,该字典是python启动后就加载在内存中。每当程序员导入新的模
块,sys.modules将自动记录该模块。当第二次再导入该模块时,python会直接到字典中查找,从而加快
了程序运行的速度。它拥有字典所拥有的一切方法。

例:modules.py
#!/usr/bin/env python
import sys
print sys.modules.keys()
print sys.modules.values()
print sys.modules["os"]

运行:
python modules.py
['copy_reg', 'sre_compile', '_sre', 'encodings', 'site', '__builtin__',......

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sys.builtin_module_names
sys.builtin_module_names返回一个列表,包含内建模块的名字。如:
>>> import sys
>>> print sys.builtin_module_names
('__builtin__', '__main__', '_ast', '_bisect', '_codecs', '_codecs_cn', '_codecs_hk',
'_codecs_iso2022', '_codecs_jp', '_codecs_kr', '_codecs_tw', '_collections', '_csv', '_functools',
'_heapq', '_hotshot', '_io', '_json', '_locale', '_lsprof', '_md5', '_multibytecodec', '_random', '_sha',
'_sha256', '_sha512', '_sre', '_struct', '_subprocess', '_symtable', '_warnings', '_weakref',
'_winreg', 'array', 'audioop', 'binascii', 'cPickle', 'cStringIO', 'cmath', 'datetime', 'errno',
'exceptions', 'future_builtins', 'gc', 'imageop', 'imp', 'itertools', 'marshal', 'math', 'mmap',
'msvcrt', 'nt', 'operator', 'parser', 'signal', 'strop', 'sys', 'thread', 'time', 'xxsubtype', 'zipimport',
'zlib')

例:
# encoding: utf-8
# find_module.py
import sys
# print sys.builtin_module_names
def find_module(module):
if module in sys.builtin_module_names:
print module," => ","__builtin__"
else:
print module,"=> ",__import__(module).__file__

find_module('os')
find_module('sys')
find_module('strop')
find_module('zlib')
find_module('string')

# 运行结果:
os => E:\Python27\lib\os.pyc
sys => __builtin__
strop => __builtin__
zlib => __builtin__
string => E:\Python27\lib\string.pyc

获取管道输入数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
使用sys.stdin.read来获取管道的输入。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import sys
a=sys.stdin.read()
print a,

[root@master ~]# echo hello | python b.py
hello

注意:
为什么多了一个空行。这是因为echo本身会给文本加换行符,而print函数又加了一个。
python3给print一个end=""参数就可以了。即,print("来自Python的:", sys.stdin.read(), end="") python2在最后加一个逗号就可以

获取数据行数脚本:
[root@master ~]# cat count.py
#!/usr/bin/env python
import sys
bi = sys.stdin.read()
li = bi.split("\n")[:-1]
print len(li)

[root@master ~]# ls | python count.py
22





文件重定向

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
在Python中,文件对象sys.stdin、sys.stdout和sys.stderr分别对应解释器的标准输入、标准输出和标准
出错流。

打开一个普通文件:
In [3]: f = open("a.txt",'w')
In [4]: f
Out[4]: <open file 'a.txt', mode 'w' at 0x243b660>

sys.stdin、sys.stdout和sys.stderr是3个已经被打开的文件:
In [2]: for fd in (sys.stdout,sys.stderr,sys.stdin):
...: print fd
...:
<open file '<stdout>', mode 'w' at 0x7fdfd8511150>
<open file '<stderr>', mode 'w' at 0x7fdfd85111e0>
<open file '<stdin>', mode 'r' at 0x7fdfd85110c0>

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
print语句不以逗号结尾时,会在输出字符串尾部自动附加一个换行符(linefeed);否则将一个空
格代替附加的换行符。print语句默认写入标准输出流,也可重定向至文件或其他可写对象(所有提
供write方法的对象)。这样,就可以使用简洁的print语句代替笨拙的object.write('hello'+'\n')
写法。
由上可知,在Python中调用print obj打印对象时,缺省情况下等效于调用sys.stdout.write(obj
+'\n')

示例如下:
>>> import sys
>>> print 'Hello World'
Hello World
>>> sys.stdout.write('Hello World')
Hello World

[root@master ~]# cat a.py
#!/usr/bin/env python
import sys
sys.stdout.write('hello')
[root@master ~]# python a.py
hello[root@master ~]#
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
重定向方式
常用的Python标准输出重定向方式有多种。这些方法各有优劣之处,适用于不同的场景。

控制台重定向
最简单常用的输出重定向方式是利用控制台命令。这种重定向由控制台完成,而与Python本身无
关。
Windows命令提示符(cmd.exe)和Linux Shell(bash等)均通过">"或">>"将输出重定向。其
中,">"表示覆盖内容,">>"表示追加内容。类似地,"2>"可重定向标准错误。重定向
到"nul"(Windows)或"/dev/null"(Linux)会抑制输出,既不屏显也不存盘。

以Windows命令提示符为例,将Python脚本输出重定向到文件:
E:\>echo print 'hello' > test.py
E:\>test.py > out.txt
E:\>type out.txt
hello
E:\>test.py >> out.txt
E:\>type out.txt
hello
hello
E:\>test.py > nul

注意,在Windows命令提示符中执行Python脚本时,命令行无需以"python"开头,系统会根据
脚本后缀自动调用Python解释器。此外,type命令可直接显示文本文件的内容,类似Linux系统
的cat命令。

Linux Shell中执行Python脚本时,命令行应以"python"开头。除">"或">>"重定向外,还可使
用tee命令。该命令可将内容同时输出到终端屏幕和(多个)文件中,"-a"选项表示追加写入,否则
覆盖写入。示例如下(echo $SHELL或echo $0显示当前所使用的Shell):

[wing@localhost ~]$ echo $SHELL
/bin/bash
[wing@localhost ~]$ python -c "print 'hello'"
hello
[wing@localhost ~]$ python -c "print 'hello'" > out.txt
[wing@localhost ~]$ cat out.txt
hello
[wing@localhost ~]$ python -c "print 'world'" >> out.txt
[wing@localhost ~]$ cat out.txt
hello
world
[wing@localhost ~]$ python -c "print 'I am'" | tee out.txt
I am
[wing@localhost ~]$ python -c "print 'wing'" | tee -a out.txt
wing
[wing@localhost ~]$ cat out.txt
I am
wing
[wing@localhost ~]$ python -c "print 'hello'" > /dev/null

注意,控制台重定向仅适用于比较简单的输出任务。

print >>重定向
这种方式基于print语句的扩展形式,即"print obj >> expr"。其中,obj为一个file-like(尤其是
提供write方法的)对象,为None时对应标准输出(sys.stdout)。expr将被输出到该文件对象中。

示例如下:
memo = cStringIO.StringIO()
serr = sys.stderr
file = open('out.txt', 'w+')
print >>memo, 'StringIO'
print >>serr, 'stderr'
print >>file, 'file'
print >>None, memo.getvalue()
上述代码执行后,屏显为"serr"和"StringIO"(两行,注意顺序),out.txt文件内写入"file"。
可见,这种方式非常灵活和方便。缺点是不适用于输出语句较多的场景。

sys.stdout重定向
将一个可写对象(如file-like对象)赋给sys.stdout,可使随后的print语句输出至该对象。重定向结
束后,应将sys.stdout恢复最初的缺省值,即标准输出。

示例如下:
import sys
savedStdout = sys.stdout #保存标准输出流
with open('out.txt', 'w+') as file:
sys.stdout = file #标准输出重定向至文件
print 'This message is for file!'
sys.stdout = savedStdout #恢复标准输出流
print 'This message is for screen!'

注意,IDLE中sys.stdout初值为PseudoOutputFile对象,与sys.__stdout__并不相同。为求
通用,本例另行定义变量(savedStdout)保存sys.stdout,下文也将作此处理。

以下将自定义多种具有write()方法的file-like对象,以满足不同需求:
import os, sys, cStringIO
class RedirectStdout:
def __init__(self):
self.content = ''
self.savedStdout = sys.stdout
self.memObj, self.fileObj, self.nulObj = None, None, None
#外部的print语句将执行本write()方法,并由当前sys.stdout输出
def write(self, outStr):
#self.content.append(outStr)
self.content += outStr

def toCons(self): #标准输出重定向至控制台
sys.stdout = self.savedStdout #sys.__stdout__

def toMemo(self): #标准输出重定向至内存
self.memObj = cStringIO.StringIO()
sys.stdout = self.memObj

def toFile(self, file='out.txt'): #标准输出重定向至文件
self.fileObj = open(file, 'a+', 1) #改为行缓冲
sys.stdout = self.fileObj

def toMute(self): #抑制输出
self.nulObj = open(os.devnull, 'w')
sys.stdout = self.nulObj

def restore(self):
self.content = ''
if self.memObj.closed != True:
self.memObj.close()
if self.fileObj.closed != True:
self.fileObj.close()
if self.nulObj.closed != True:
self.nulObj.close()
sys.stdout = self.savedStdout #sys.__stdout__

注意,toFile()方法中,open(name[, mode[, buffering]])调用选择行缓冲(无缓冲会影响性能)。这是为了观察中间写入过程,否则只有调用close()或flush()后输出才会写入文件。内部调用
open()方法的缺点是不便于用户定制写文件规则,如模式(覆盖或追加)和缓冲(行或全缓冲)。

重定向效果如下:
redirObj = RedirectStdout()
sys.stdout = redirObj
#本句会抑制"Let's begin!"输出
print "Let's begin!"

#屏显'Hello World!'和'I am wing.'(两行)
redirObj.toCons(); print 'Hello World!'; print 'I am wing.'
#写入'How are you?'和"Can't complain."(两行)
redirObj.toFile(); print 'How are you?'; print "Can't complain."
redirObj.toCons(); print "What'up?" #屏显
redirObj.toMute(); print '<Silence>' #无屏显或写入
os.system('echo Never redirect me!') #控制台屏显'Never redirect me!'
redirObj.toMemo(); print 'What a pity!' #无屏显或写入
redirObj.toCons(); print 'Hello?' #屏显
redirObj.toFile(); print "Oh, wing can't hear me" #该串写入文件
redirObj.restore()

print 'Pop up' #屏显
可见,执行toXXXX()语句后,标准输出流将被重定向到XXXX。此外,toMute()和toMemo()的
效果类似,均可抑制输出。
使用某对象替换sys.stdout时,尽量确保该对象接近文件对象,尤其是涉及第三方库时(该库可能
使用sys.stdout的其他方法)。此外,本节替换sys.stdout的代码实现并不影响由os.popen()、
os.system()或os.exec*()系列方法所创建进程的标准I/O流。

上下文管理器(Context Manager)
严格意义上并非新的重定向方式,而是利用Pyhton上下文管理器优化上节的代码实现。借助于上
下文管理器语法,可不必向重定向使用者暴露sys.stdout。
首先考虑输出抑制,基于上下文管理器语法实现如下:

import sys, cStringIO, contextlib
class DummyFile:
def write(self, outStr): pass

@contextlib.contextmanager
def MuteStdout():
savedStdout = sys.stdout
sys.stdout = cStringIO.StringIO() #DummyFile()
try:
yield
except Exception: #捕获到错误时,屏显被抑制的输出(该处理并非必需)
content, sys.stdout = sys.stdout, savedStdout
print content.getvalue()#; raise
#finally:
sys.stdout = savedStdout

使用示例如下:
with MuteStdout():
print "I'll show up when <raise> is executed!" #不屏显不写入
raise #屏显上句
print "I'm hiding myself somewhere:)" #不屏显再考虑更通用的输出重定向:

import os, sys
from contextlib import contextmanager
@contextmanager
def RedirectStdout(newStdout):
savedStdout, sys.stdout = sys.stdout, newStdout
try:
yield
finally:
sys.stdout = savedStdout
使用示例如下:

def Greeting(): print 'Hello, boss!'

with open('out.txt', "w+") as file:
print "I'm writing to you..." #屏显
with RedirectStdout(file):
print 'I hope this letter finds you well!' #写入文件
print 'Check your mailbox.' #屏显

with open(os.devnull, "w+") as file, RedirectStdout(file):
Greeting() #不屏显不写入
print 'I deserve a pay raise:)' #不屏显不写入
print 'Did you hear what I said?' #屏显
可见,with内嵌块里的函数和print语句输出均被重定向。注意,上述示例不是线程安全的,主要
适用于单线程。
当函数被频繁调用时,建议使用装饰器包装该函数。这样,仅需修改该函数定义,而无需在每次
调用该函数时使用with语句包裹。示例如下:
import sys, cStringIO, functools
def MuteStdout(retCache=False):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
savedStdout = sys.stdout
sys.stdout = cStringIO.StringIO()
try:
ret = func(*args, **kwargs)
if retCache == True:
ret = sys.stdout.getvalue().strip()
finally:
sys.stdout = savedStdout
return ret
return wrapper
return decorator
若装饰器MuteStdout的参数retCache为真,外部调用func()函数时将返回该函数内部print输出的内容(可
供屏显);若retCache为假,外部调用func()函数时将返回该函数的返回值(抑制输出)。
MuteStdout装饰器使用示例如下:

@MuteStdout(True)
def Exclaim(): print 'I am proud of myself!'

@MuteStdout()
def Mumble(): print 'I lack confidence...'; return 'sad'

print Exclaim(), Exclaim.__name__ #屏显'I am proud of myself! Exclaim'
print Mumble(), Mumble.__name__ #屏显'sad Mumble'
在所有线程中,被装饰函数执行期间,sys.stdout都会被MuteStdout装饰器劫持。而且,函数一经装饰便
无法移除装饰。因此,使用该装饰器时应慎重考虑场景。
接着,考虑创建RedirectStdout装饰器:

def RedirectStdout(newStdout=sys.stdout):
def decorator(func):
def wrapper(*args,**kwargs):
savedStdout, sys.stdout = sys.stdout, newStdout
try:
return func(*args, **kwargs)
finally:
sys.stdout = savedStdout
return wrapper
return decorator
使用示例如下:
file = open('out.txt', "w+")
@RedirectStdout(file)
def FunNoArg(): print 'No argument.'

@RedirectStdout(file)
def FunOneArg(a): print 'One argument:', a

def FunTwoArg(a, b): print 'Two arguments: %s, %s' %(a,b)

FunNoArg() #写文件'No argument.'
FunOneArg(1984) #写文件'One argument: 1984'
RedirectStdout()(FunTwoArg)(10,29) #屏显'Two arguments: 10, 29'
print FunNoArg.__name__ #屏显'wrapper'(应显示'FunNoArg')

file.close()
注意FunTwoArg()函数的定义和调用与其他函数的不同,这是两种等效的语法。此外,RedirectStdout装饰
器的最内层函数wrapper()未使用"functools.wraps(func)"修饰,会丢失被装饰函数原有的特殊属性(如函
数名、文档字符串等)。

logging模块重定向
对于代码量较大的工程,建议使用logging模块进行输出。该模块是线程安全的,可将日志信息输出
到控制台、写入文件、使用TCP/UDP协议发送到网络等等。
默认情况下logging模块将日志输出到控制台(标准出错),且只显示大于或等于设置的日志级别的日
志。日志级别由高到低为CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET,默认
级别为WARNING。
以下示例将日志信息分别输出到控制台和写入文件:
import logging
logging.basicConfig(level = logging.DEBUG,
format = '%(asctime)s [%(levelname)s] at %(filename)s,%(lineno)d: %(message)s',
datefmt = '%Y-%m-%d(%a)%H:%M:%S',
filename = 'out.txt',
filemode = 'w')

#将大于或等于INFO级别的日志信息输出到StreamHandler(默认为标准错误)
console = logging.StreamHandler()
console.setLevel(logging.INFO)
formatter = logging.Formatter('[%(levelname)-8s] %(message)s') #屏显实时查看,无需时间
console.setFormatter(formatter)
logging.getLogger().addHandler(console)

logging.debug('gubed'); logging.info('ofni'); logging.critical('lacitirc')
通过对多个handler设置不同的level参数,可将不同的日志内容输入到不同的地方。本例使用在logging模
块内置的StreamHandler(和FileHandler),运行后屏幕上显示:

[INFO ] ofni
[CRITICAL] lacitirc
out.txt文件内容则为:
2016-05-13(Fri)17:10:53 [DEBUG] at test.py,25: gubed
2016-05-13(Fri)17:10:53 [INFO] at test.py,25: ofni
2016-05-13(Fri)17:10:53 [CRITICAL] at test.py,25: lacitirc
除直接在程序中设置Logger、Handler、Formatter等外,还可将这些信息写入配置文件。
示例如下:
#logger.conf
###############Logger###############
[loggers]
keys=root,Logger2F,Logger2CF

[logger_root]
level=DEBUG
handlers=hWholeConsole

[logger_Logger2F]
handlers=hWholeFile
qualname=Logger2F
propagate=0

[logger_Logger2CF]
handlers=hPartialConsole,hPartialFile
qualname=Logger2CF
propagate=0

###############Handler###############
[handlers]
keys=hWholeConsole,hPartialConsole,hWholeFile,hPartialFile

[handler_hWholeConsole]
class=StreamHandler
level=DEBUG
formatter=simpFormatter
args=(sys.stdout,)

[handler_hPartialConsole]
class=StreamHandler
level=INFO
formatter=simpFormatter
args=(sys.stderr,)

[handler_hWholeFile]
class=FileHandler
level=DEBUG
formatter=timeFormatter
args=('out.txt', 'a')

[handler_hPartialFile]
class=FileHandler
level=WARNING
formatter=timeFormatter
args=('out.txt', 'w')

###############Formatter###############
[formatters]
keys=simpFormatter,timeFormatter

[formatter_simpFormatter]
format=[%(levelname)s] at %(filename)s,%(lineno)d: %(message)s

[formatter_timeFormatter]
format=%(asctime)s [%(levelname)s] at %(filename)s,%(lineno)d: %(message)s
datefmt=%Y-%m-%d(%a)%H:%M:%S
此处共创建三个Logger:root,将所有日志输出至控制台;Logger2F,将所有日志写入文件;
Logger2CF,将级别大于或等于INFO的日志输出至控制台,将级别大于或等于WARNING的日志写入文
件。
程序以如下方式解析配置文件和重定向输出:
import logging, logging.config
logging.config.fileConfig("logger.conf")

logger = logging.getLogger("Logger2CF")
logger.debug('gubed'); logger.info('ofni'); logger.warn('nraw')
logger.error('rorre'); logger.critical('lacitirc')

logger1 = logging.getLogger("Logger2F")
logger1.debug('GUBED'); logger1.critical('LACITIRC')

logger2 = logging.getLogger()
logger2.debug('gUbEd'); logger2.critical('lAcItIrC')
运行后屏幕上显示:
[INFO] at test.py,7: ofni
[WARNING] at test.py,7: nraw
[ERROR] at test.py,8: rorre
[CRITICAL] at test.py,8: lacitirc
[DEBUG] at test.py,14: gUbEd
[CRITICAL] at test.py,14: lAcItIrC

out.txt文件内容则为:
2016-05-13(Fri)20:31:21 [WARNING] at test.py,7: nraw
2016-05-13(Fri)20:31:21 [ERROR] at test.py,8: rorre
2016-05-13(Fri)20:31:21 [CRITICAL] at test.py,8: lacitirc
2016-05-13(Fri)20:31:21 [DEBUG] at test.py,11: GUBED
2016-05-13(Fri)20:31:21 [CRITICAL] at test.py,11: LACITIRC

总结
以上就是关于Python标准输出的重定向方式的全部内容

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#!/usr/bin/env python
import sys
saveout = sys.stdout #保存原来的stdout

f = open('out.log', 'w')
sys.stdout = f #以后的stdout会重定向到f(out.log)里
print 'This message will be logged instead of displayed'

sys.stdout = saveout #把原来的stdout还原回去
f.close()