Python 常用模块大全(整理)
OS 模块
#os 模块就是对操作系统进行操作,使用该模块必须先导入模块:
import os
#getcwd()获取当前工作目录 ( 当前工作目录默认都是当前文件所在的文件夹)
result = os.getcwd()
print(result)
#chdir() 改变当前工作目录
os.chdir('/home/sy')
result = os.getcwd()
print(result)
open('02.txt','w')
#操作时如果书写完整的路径则不需要考虑默认工作目录的问题, 按照实际书写路径操作
open('/home/sy/ 下载 /02.txt','w')
#listdir() 获取指定文件夹中所有内容的名称列表
result = os.listdir('/home/sy')
print(result)
#mkdir() 创建文件夹
#os.mkdir('girls')
#os.mkdir('boys',0o777)
#makedirs() 递归创建文件夹
#os.makedirs('/home/sy/a/b/c/d')
#rmdir() 删除空目录
#os.rmdir('girls')
#removedirs 递归删除文件夹 必须都是空目录
#os.removedirs('/home/sy/a/b/c/d')
#rename() 文件或文件夹重命名
#os.rename('/home/sy/a','/home/sy/alibaba'
#os.rename('02.txt','002.txt')
#stat() 获取文件或者文件夹的信息
#result = os.stat('/home/sy/PycharmProject/Python3/10.27/01.py)
#print(result)
#system()执行系统命令 ( 危险函数)
#result = os.system('ls -al') #获取隐藏文件
#print(result)
#环境变量
'''
环境变量就是一些命令的集合
操作系统的环境变量就是操作系统在执行系统命令时搜索命令的目录的集合
'''
#getenv() 获取系统的环境变量
result = os.getenv('PATH')
print(result.split(':'))
#putenv()将一个目录添加到环境变量中 ( 临时增加仅对当前脚本有效)
#os.putenv('PATH','/home/sy/ 下载')
#os.system('syls')
#exit() 退出终端的命令
#os 模块中的常用值
#curdir 表示当前文件夹 . 表示当前文件夹 一般情况下可以省略
print(os.curdir)
#pardir 表示上一层文件夹 .. 表示上一层文件夹 不可省略!
print(os.pardir)
#os.mkdir('../../../man')# 相对路径 从当前目录开始查找
#os.mkdir('/home/sy/man1')# 绝对路径 从根目录开始查找
#name 获取代表操作系统的名称字符串
print(os.name) #posix -> linux 或者 unix 系统 nt -> window 系统
#sep 获取系统路径间隔符号 window ->\ linux ->/
print(os.sep)
#extsep 获取文件名称和后缀之间的间隔符号 window & linux -> .
print(os.extsep)
#linesep 获取操作系统的换行符号 window -> \r\n linux/unix -> \n
print(repr(os.linesep))
#导入 os 模块
import os
#以下内容都是 os.path 子模块中的内容
#abspath() 将相对路径转化为绝对路径
path = './boys'#相对
result = os.path.abspath(path)
print(result)
#dirname()获取完整路径当中的目录部分 & basename() 获取完整路径当中的主体部分
path = '/home/sy/boys'
result = os.path.dirname(path)
print(result)
result = os.path.basename(path)
print(result)
#split() 将一个完整的路径切割成目录部分和主体部分
path = '/home/sy/boys'
result = os.path.split(path)
print(result)
#join() 将 2 个路径合并成一个
var1 = '/home/sy'
var2 = '000.py'
result = os.path.join(var1,var2)
print(result)
#splitext() 将一个路径切割成文件后缀和其他两个部分, 主要用于获取文件的后缀
path = '/home/sy/000.py'
result = os.path.splitext(path)
print(result)
#getsize() 获取文件的大小
#path = '/home/sy/000.py'
#result = os.path.getsize(path)
#print(result)
#isfile() 检测是否是文件
path = '/home/sy/000.py'
result = os.path.isfile(path)
print(result)
#isdir() 检测是否是文件夹
result = os.path.isdir(path)
print(result)
#islink() 检测是否是链接
path = '/initrd.img.old'
result = os.path.islink(path)
print(result)
#getctime() 获取文件的创建时间 get create time
#getmtime() 获取文件的修改时间 get modify time
#getatime() 获取文件的访问时间 get active time
import time
filepath = '/home/sy/ 下载 /chls'
result = os.path.getctime(filepath)
print(time.ctime(result))
result = os.path.getmtime(filepath)
print(time.ctime(result))
result = os.path.getatime(filepath)
print(time.ctime(result))
#exists() 检测某个路径是否真实存在
filepath = '/home/sy/ 下载 /chls'
result = os.path.exists(filepath)
print(result)
#isabs() 检测一个路径是否是绝对路径
path = '/boys'
result = os.path.isabs(path)
print(result)
#samefile() 检测 2 个路径是否是同一个文件
path1 = '/home/sy/ 下载 /001'
path2 = '../../../ 下载 /001'
result = os.path.samefile(path1,path2)
print(result)
#os.environ 用于获取和设置系统环境变量的内置值
import os
#获取系统环境变量 getenv() 效果
print(os.environ['PATH'])
#设置系统环境变量 putenv()os.environ['PATH'] += ':/home/sy/ 下载'
os.system('chls')
os 常用方法
os.remove(‘path/filename’) 删除文件
os.rename(oldname, newname) 重命名文件
os.walk() 生成目录树下的所有文件名
os.chdir('dirname') 改变目录
os.mkdir/makedirs('dirname') 创建目录 / 多层目录
os.rmdir/removedirs('dirname') 删除目录 / 多层目录
os.listdir('dirname') 列出指定目录的文件
os.getcwd() 取得当前工作目录
os.chmod() 改变目录权限
os.path.basename(‘path/filename’) 去掉目录路径,返回文件名
os.path.dirname(‘path/filename’) 去掉文件名,返回目录路径
os.path.join(path1[,path2[,...]]) 将分离的各部分组合成一个路径名
os.path.split('path') 返回 (dirname(), basename()) 元组
os.path.splitext()返回 (filename, extension) 元组
os.path.getatime\ctime\mtime 分别返回最近访问、创建、修改时间
os.path.getsize() 返回文件大小
os.path.exists() 是否存在
os.path.isabs() 是否为绝对路径
os.path.isdir() 是否为目录
os.path.isfile() 是否为文件
sys 模块
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.stdin,sys.stdout,sys.stderr
我们常用print和raw_input来进行输入和打印,那么
print 和 raw_input 是如何与标准输入 / 输出流建立关系的呢?其实 Python 程序的标准输入 / 输出 / 出错流定义在 sys 模块中,分别 为: sys.stdin,sys.stdout, sys.stderr
下列的程序也可以用来输入和输出是一样的:
import sys
sys.stdout.write('HelloWorld!')
print 'Please enter yourname:',
name=sys.stdin.readline()[:-1]
print 'Hi, %s!' % name
那么 sys.stdin, sys.stdout, stderr 到底是什么呢?我们在 Python 运行环境中输入以下代码:
import sys
for f in (sys.stdin,sys.stdout, sys.stderr): print f
输出为:
<open file'<stdin>', mode 'r' at 892210>
<open file'<stdout>', mode 'w' at 892270>
<open file'<stderr>', mode 'w at 8922d0>
由此可以看出 stdin, stdout, stderr 在 Python 中无非都是文件属性的对象,他们在 Python 启动时自动与 Shell 环境中的标准输入,输出,出错关联。
而 Python 程序的在 Shell 中的 I/O 重定向与本文开始时举的 DOS 命令的重定向完全相同,其实这种重定向是由 Shell 来提供的,与 Python 本身并无关系。那么我们是否可以在 Python 程序内部将 stdin,stdout,stderr 读写操作重定向到一个内部对象呢?答案是肯定的。
Python 提供了一个 StringIO 模块来完成这个设想,比如:
from StringIO import StringIO
import sys
buff =StringIO()
temp =sys.stdout # 保存标准 I/O 流
sys.stdout =buff # 将标准 I/O 流重定向到 buff 对象
print 42, 'hello', 0.001
sys.stdout=temp # 恢复标准 I/O 流
print buff.getvalue()
time 模块中时间表现的格式主要有三种:
a、timestamp 时间戳,时间戳表示的是从 1970 年 1 月 1 日 00:00:00 开始按秒计算的偏移量
b、struct_time 时间元组,共有九个元素组。
c、format time 格式化时间,已格式化的结构使时间更具可读性。包括自定义格式和固定格式。
1、时间格式转换图:
2、主要 time 生成方法和 time 格式转换方法实例:
#! /usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = "TKQ"
import time
# 生成 timestamp
time.time()
# 1477471508.05
#struct_time to timestamp
time.mktime(time.localtime())
#生成 struct_time
# timestamp to struct_time 本地时间
time.localtime()time.localtime(time.time())
# time.struct_time(tm_year=2016, tm_mon=10, tm_mday=26, tm_hour=16, tm_min=45, tm_sec=8, tm_wday=2, tm_yday=300, tm_isdst=0)
# timestamp to struct_time 格林威治时间
time.gmtime()time.gmtime(time.time())
# time.struct_time(tm_year=2016, tm_mon=10, tm_mday=26, tm_hour=8, tm_min=45, tm_sec=8, tm_wday=2, tm_yday=300, tm_isdst=0)
#format_time to struct_time
time.strptime('2011-05-05 16:37:06', '%Y-%m-%d %X')
# time.struct_time(tm_year=2011, tm_mon=5, tm_mday=5, tm_hour=16, tm_min=37, tm_sec=6, tm_wday=3, tm_yday=125, tm_isdst=-1)
#生成 format_time
#struct_time to format_time
time.strftime("%Y-%m-%d %X")
time.strftime("%Y-%m-%d %X",time.localtime())
# 2016-10-26 16:48:41
#生成固定格式的时间表示格式
time.asctime(time.localtime())
time.ctime(time.time())
# Wed Oct 26 16:45:08 2016
struct_time 元组元素结构
属性 值
tm_year(年) 比如 2011
tm_mon(月) 1 - 12
tm_mday(日) 1 - 31
tm_hour(时) 0 - 23
tm_min(分) 0 - 59
tm_sec(秒) 0 - 61
tm_wday(weekday) 0 - 6(0 表示周日)
tm_yday(一年中的第几天) 1 - 366
tm_isdst(是否是夏令时) 默认为 -1
format time 结构化表示
格式 | 含义 |
%a | 本地(locale)简化星期名称 |
%A | 本地完整星期名称 |
%b | 本地简化月份名称 |
%B | 本地完整月份名称 |
%c | 本地相应的日期和时间表示 |
%d | 一个月中的第几天(01 - 31) |
%H | 一天中的第几个小时(24 小时制,00 - 23) |
%I | 第几个小时(12 小时制,01 - 12) |
%j | 一年中的第几天(001 - 366) |
%m | 月份(01 - 12) |
%M | 分钟数(00 - 59) |
%p | 本地 am 或者 pm 的相应符 |
%S | 秒(01 - 61) |
%U | 一年中的星期数。(00 - 53 星期天是一个星期的开始。)第一个星期天之前的所有天数都放在第 0 周。 |
%w | 一个星期中的第几天(0 - 6,0 是星期天) |
%W | 和 %U 基本相同,不同的是 %W 以星期一为一个星期的开始。 |
%x | 本地相应日期 |
%X | 本地相应时间 |
%y | 去掉世纪的年份(00 - 99) |
%Y | 完整的年份 |
%Z | 时区的名字(如果不存在为空字符) |
%% | ‘%’字符 |
常见结构化时间组合:
print time.strftime("%Y-%m-%d %X")
#2016-10-26 20:50:13
3、time 加减
#timestamp 加减单位以秒为单位
import time
t1 = time.time()
t2=t1+10
print time.ctime(t1)#Wed Oct 26 21:15:30 2016
print time.ctime(t2)#Wed Oct 26 21:15:40 2016
datetime 模块
datatime 模块重新封装了 time 模块,提供更多接口,提供的类有:date,time,datetime,timedelta,tzinfo。
1、date 类
datetime.date(year, month, day)
静态方法和字段
date.max、date.min:date 对象所能表示的最大、最小日期;
date.resolution:date 对象表示日期的最小单位。这里是天。
date.today():返回一个表示当前本地日期的 date 对象;
date.fromtimestamp(timestamp):根据给定的时间戮,返回一个 date 对象;
方法和属性
d1 = date(2011,06,03)#date 对象
d1.year、date.month、date.day:年、月、日;
d1.replace(year, month, day):生成一个新的日期对象,用参数指定的年,月,日代替原有对象中的属性。(原有对象仍保持不变)
d1.timetuple():返回日期对应的 time.struct_time 对象;
d1.weekday():返回 weekday,如果是星期一,返回 0;如果是星期 2,返回 1,以此类推;
d1.isoweekday():返回 weekday,如果是星期一,返回 1;如果是星期 2,返回 2,以此类推;
d1.isocalendar():返回格式如 (year,month,day) 的元组;
d1.isoformat():返回格式如'YYYY-MM-DD’的字符串;
d1.strftime(fmt):和 time 模块 format 相同。
2、time 类
datetime.time(hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] )
静态方法和字段
time.min、time.max:time 类所能表示的最小、最大时间。其中,time.min = time(0, 0, 0, 0), time.max = time(23, 59, 59, 999999);
time.resolution:时间的最小单位,这里是 1 微秒;
方法和属性
t1 = datetime.time(10,23,15)#time 对象
t1.hour、t1.minute、t1.second、t1.microsecond:时、分、秒、微秒;
t1.tzinfo:时区信息;
t1.replace([hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ] ):创建一个新的时间对象,用参数指定的时、分、秒、微秒代替原有对象中的属性(原有对象仍保持不变);
t1.isoformat():返回型如"HH:MM:SS"格式的字符串表示;
t1.strftime(fmt):同 time 模块中的 format;
3、datetime 类
datetime 相当于 date 和 time 结合起来。
datetime.datetime (year, month, day[ , hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ] )
静态方法和字段
datetime.today():返回一个表示当前本地时间的 datetime 对象;
datetime.now([tz]):返回一个表示当前本地时间的 datetime 对象,如果提供了参数 tz,则获取 tz 参数所指时区的本地时间;
datetime.utcnow():返回一个当前 utc 时间的 datetime 对象;# 格林威治时间
datetime.fromtimestamp(timestamp[, tz]):根据时间戮创建一个 datetime 对象,参数 tz 指定时区信息;
datetime.utcfromtimestamp(timestamp):根据时间戮创建一个 datetime 对象;
datetime.combine(date, time):根据 date 和 time,创建一个 datetime 对象;
datetime.strptime(date_string, format):将格式字符串转换为 datetime 对象;
方法和属性
dt=datetime.now()#datetime 对象
dt.year、month、day、hour、minute、second、microsecond、tzinfo:
dt.date():获取 date 对象;
dt.time():获取 time 对象;
dt. replace ([year[ , month[ , day[ , hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ] ] ] ]):
dt. timetuple ()dt. utctimetuple ()
dt. toordinal ()dt. weekday ()
dt. isocalendar ()dt. isoformat ([ sep] )dt. ctime ():返回一个日期时间的 C 格式字符串,等效于 time.ctime(time.mktime(dt.timetuple()));
dt. strftime (format)
4.timedelta 类,时间加减
使用 timedelta 可以很方便的在日期上做天 days,小时 hour,分钟,秒,毫秒,微妙的时间计算,如果要计算月份则需要另外的办法。
#coding:utf-8
from datetime import *
dt = datetime.now()
#日期减一天
dt1 = dt + timedelta(days=-1)#昨天
dt2 = dt - timedelta(days=1)#昨天
dt3 = dt + timedelta(days=1)#明天
delta_obj = dt3-dt
print type(delta_obj),delta_obj#<type 'datetime.timedelta'> 1 day, 0:00:00
print delta_obj.days ,delta_obj.total_seconds()#1 86400.0
5、tzinfo 时区类
#! /usr/bin/python
# coding=utf-8
from datetime import datetime, tzinfo,timedelta
"""
tzinfo 是关于时区信息的类
tzinfo 是一个抽象类,所以不能直接被实例化
"""
class UTC(tzinfo):
"""UTC"""
def init(self,offset = 0):
self._offset = offset
<span style="color: rgba(0, 0, 255, 1)">def<span style="color: rgba(0, 0, 0, 1)"> utcoffset(self, dt):
<span style="color: rgba(0, 0, 255, 1)">return timedelta(hours=<span style="color: rgba(0, 0, 0, 1)">self._offset)
<span style="color: rgba(0, 0, 255, 1)">def<span style="color: rgba(0, 0, 0, 1)"> tzname(self, dt):
<span style="color: rgba(0, 0, 255, 1)">return <span style="color: rgba(128, 0, 0, 1)">"<span style="color: rgba(128, 0, 0, 1)">UTC +%s<span style="color: rgba(128, 0, 0, 1)">" %<span style="color: rgba(0, 0, 0, 1)"> self._offset
<span style="color: rgba(0, 0, 255, 1)">def<span style="color: rgba(0, 0, 0, 1)"> dst(self, dt):
<span style="color: rgba(0, 0, 255, 1)">return timedelta(hours=<span style="color: rgba(0, 0, 0, 1)">self._offset)
#北京时间
beijing = datetime(2011,11,11,0,0,0,tzinfo = UTC(8))
print "beijing time:",beijing
#曼谷时间
bangkok = datetime(2011,11,11,0,0,0,tzinfo = UTC(7))
print "bangkok time",bangkok
#北京时间转成曼谷时间
print "beijing-time to bangkok-time:",beijing.astimezone(UTC(7))
#计算时间差时也会考虑时区的问题
timespan = beijing - bangkok
print "时差:",timespan
#Output==================
# beijing time: 2011-11-11 00:00:00+08:00
# bangkok time 2011-11-11 00:00:00+07:00
# beijing-time to bangkok-time: 2011-11-10 23:00:00+07:00
# 时差: -1 day, 23:00:00
hashlib 加密
hashlib 主要提供字符加密功能,将 md5 和 sha 模块整合到了一起,支持 md5,sha1, sha224, sha256, sha384, sha512 等算法
具体应用
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#pyversion:python3.5
#owner:fuzj
import hashlib
# ######## md5 ########
string = "beyongjie"
md5 = hashlib.md5()
md5.update(string.encode('utf-8')) #注意转码
res = md5.hexdigest()
print("md5 加密结果:",res)
# ######## sha1 ########
sha1 = hashlib.sha1()
sha1.update(string.encode('utf-8'))
res = sha1.hexdigest()
print("sha1 加密结果:",res)
# ######## sha256 ########
sha256 = hashlib.sha256()
sha256.update(string.encode('utf-8'))
res = sha256.hexdigest()
print("sha256 加密结果:",res)
# ######## sha384 ########
sha384 = hashlib.sha384()
sha384.update(string.encode('utf-8'))
res = sha384.hexdigest()
print("sha384 加密结果:",res)
# ######## sha512 ########
sha512= hashlib.sha512()
sha512.update(string.encode('utf-8'))
res = sha512.hexdigest()
print("sha512 加密结果:",res)
输出结果:
md5 加密结果: 0e725e477851ff4076f774dc312d4748
sha1 加密结果: 458d32be8ea38b66300174970ab0a8c0b734252f
sha256 加密结果: 1e62b55bfd02977943f885f6a0998af7cc9cfb95c8ac4a9f30ecccb7c05ec9f4
sha384 加密结果: e91cdf0d2570de5c96ee84e8a12cddf16508685e7a03b3e811099cfcd54b7f52183e20197cff7c07f312157f0ba4875b
sha512 加密结果: 3f0020a726e9c1cb5d22290c967f3dd1bcecb409a51a8088db520750c876aaec3f17a70d7981cd575ed4b89471f743f3f24a146a39d59f215ae3e208d0170073
注意:hashlib 加密啊的字符串类型为二进制编码,直接加密字符串会报如下错误:
sha1 = hashlib.sha1()sha1.update(string)
res = sha1.hexdigest()
print("sha1 加密结果:",res)
TypeError: Unicode-objects must be encoded before hashing
可以使用 encode 进行转换
shaa1 = hashlib.sha1()
shaa1.update(string.encode('utf-8'))
res = shaa1.hexdigest()
print("sha1 采用 encode 转换加密结果:",res)
或者使用 byte 转换为二进制
shab1 = hashlib.sha1()
shab1.update(bytes(string,encoding='utf-8'))
res = shab1.hexdigest()
print("sha1 采用 byte 转换的结果:",res)
以上输出:
sha1 采用 encode 转换加密结果: 458d32be8ea38b66300174970ab0a8c0b734252f
sha1 采用 byte 转换的结果: 458d32be8ea38b66300174970ab0a8c0b734252f
常用方法
- hash.update(arg) 更新哈希对象以字符串参数, 注意:如果同一个 hash 对象重复调用该方法,则 m.update(a); m.update(b) 等效于 m.update(a+b),看下面例子
m = hashlib.md5()
m.update('a'.encode('utf-8'))
res = m.hexdigest()
print("第一次 a 加密:",res)
m.update('b'.encode('utf-8'))
res = m.hexdigest()
print("第二次 b 加密:",res)
m1 = hashlib.md5()
m1.update('b'.encode('utf-8'))
res = m1.hexdigest()
print("b 单独加密:",res)
m2 = hashlib.md5()
m2.update('ab'.encode('utf-8'))
res = m2.hexdigest()
print("ab 单独加密:",res)
输出结果:
第一次 a 加密: 0cc175b9c0f1b6a831c399e269772661
第二次 b 加密: 187ef4436122d1cc2f40dc2b92f0eba0
b 单独加密: 92eb5ffee6ae2fec3ad71c777531578f
ab 单独加密: 187ef4436122d1cc2f40dc2b92f0eba0
-
hash.digest() 返回摘要,作为二进制数据字符串值,
-
hash.hexdigest() 返回摘要,作为十六进制数据字符串值,
-
hash.copy() 复制
高级加密
以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。所以,有必要对加密算法中添加自定义 key 再来做加密。
low = hashlib.md5()
low.update('ab'.encode('utf-8'))
res = low.hexdigest()
print("普通加密:",res)
high = hashlib.md5(b'beyondjie')
high.update('ab'.encode('utf-8'))
res = high.hexdigest()
print("采用 key 加密:",res)
输出结果:
普通加密: 187ef4436122d1cc2f40dc2b92f0eba0
采用 key 加密: 1b073f6b8cffe609751e4c98537b7653
附加 HMAC-SHA1 各语言版本实现
在各大开放平台大行其道的互联网开发潮流中,调用各平台的 API 接口过程中,无一例外都会用到计算签名值 (sig 值)。而在各种计算签名的方法中,经常被采用的就是 HMAC-SHA1,现对 HMAC-SHA1 做一个简单的介绍:
HMAC,散列消息鉴别码,基于密钥的Hash算法认证协议。实现原理为:利用已经公开的Hash函数和私有的密钥,来生成固定长度的消息鉴别码;
SHA1、MD5等Hash算法是比较常用的不可逆Hash签名计算方法;
BASE64,将任意序列的8字节字符转换为人眼无法直接识别的符号编码的一种方法;
各个语言版本的实现为:
Python版:
<span style="color: rgba(0, 0, 255, 1)">import<span style="color: rgba(0, 0, 0, 1)"> hmac
<span style="color: rgba(0, 0, 255, 1)">import<span style="color: rgba(0, 0, 0, 1)"> hashlib
<span style="color: rgba(0, 0, 255, 1)">import<span style="color: rgba(0, 0, 0, 1)"> base64
hmac.new(Token,data,hashlib.sha1).digest().encode(<span style="color: rgba(128, 0, 0, 1)">'<span style="color: rgba(128, 0, 0, 1)">base64<span style="color: rgba(128, 0, 0, 1)">'<span style="color: rgba(0, 0, 0, 1)">).rstrip()
Token:即接口的 key
data:要加密的数据
PHP版:
base64_encode(hash_hmac(<span style="color: rgba(128, 0, 0, 1)">"<span style="color: rgba(128, 0, 0, 1)">SHA1<span style="color: rgba(128, 0, 0, 1)">"<span style="color: rgba(0, 0, 0, 1)">,clientStr,Token , true))
C++<span style="color: rgba(0, 0, 0, 1)">版(Openssl):
HMAC( EVP_sha1(),
/*key data*/<span style="color: rgba(0, 0, 0, 1)"> strKey.data(),
/*key len*/<span style="color: rgba(0, 0, 0, 1)"> strKey.size(),
/*data */(unsigned char*<span style="color: rgba(0, 0, 0, 1)">) strRandom.data(),
/*data len*/ strRandom.size(), digest, &<span style="color: rgba(0, 0, 0, 1)">digest_len))
Shell版:
echo -n <span style="color: rgba(128, 0, 0, 1)">'<span style="color: rgba(128, 0, 0, 1)">3f88a95c532bea70<span style="color: rgba(128, 0, 0, 1)">' | openssl dgst -hmac <span style="color: rgba(128, 0, 0, 1)">'<span style="color: rgba(128, 0, 0, 1)">123<span style="color: rgba(128, 0, 0, 1)">' -sha1 -binary | base64<br><br><br></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
1 logging 模块简介
logging 模块是 Python 内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级、日志保存路径、日志文件回滚等;相比 print,具备如下优点:
- 可以通过设置不同的日志等级,在 release 版本中只输出重要信息,而不必显示大量的调试信息;
- print 将所有信息都输出到标准输出中,严重影响开发者从标准输出中查看其它数据;logging 则可以由开发者决定将信息输出到什么地方,以及怎么输出;
2 logging 模块使用
2.1 基本使用
配置 logging 基本的设置,然后在控制台输出日志,
import logging
logging.basicConfig(level = logging.INFO,format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s')logger = logging.getLogger(__name__)
logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
logger.info("Finish")
运行时,控制台输出,
2016-10-09 19:11:19,434 - __main__ - INFO - Start print log
2016-10-09 19:11:19,434 - __main__ - WARNING - Something maybe fail.
2016-10-09 19:11:19,434 - __main__ - INFO - Finish
logging 中可以选择很多消息级别,如 debug、info、warning、error 以及 critical。通过赋予 logger 或者 handler 不同的级别,开发者就可以只输出错误信息到特定的记录文件,或者在调试时只记录调试信息。
例如,我们将 logger 的级别改为 DEBUG,再观察一下输出结果,
logging.basicConfig(level = logging.DEBUG,format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
控制台输出,可以发现,输出了 debug 的信息。
2016-10-09 19:12:08,289 - __main__ - INFO - Start print log
2016-10-09 19:12:08,289 - __main__ - DEBUG - Do something
2016-10-09 19:12:08,289 - __main__ - WARNING - Something maybe fail.
2016-10-09 19:12:08,289 - __main__ - INFO - Finish
logging.basicConfig 函数各参数:
filename:指定日志文件名;
filemode:和 file 函数意义相同,指定日志文件的打开模式,'w' 或者 'a';
format:指定输出的格式和内容,format 可以输出很多有用的信息,
参数:作用
%(levelno)s:打印日志级别的数值
%(levelname)s:打印日志级别的名称
%(pathname)s:打印当前执行程序的路径,其实就是 sys.argv[0]
%(filename)s:打印当前执行程序名
%(funcName)s:打印日志的当前函数
%(lineno)d:打印日志的当前行号
%(asctime)s:打印日志的时间
%(thread)d:打印线程 ID
%(threadName)s:打印线程名称
%(process)d:打印进程 ID
%(message)s:打印日志信息
datefmt:指定时间格式,同 time.strftime();
level:设置日志级别,默认为 logging.WARNNING;
stream:指定将日志的输出流,可以指定输出到 sys.stderr,sys.stdout 或者文件,默认输出到 sys.stderr,当 stream 和 filename 同时指定时,stream 被忽略;
2.2 将日志写入到文件
2.2.1 将日志写入到文件
设置 logging,创建一个 FileHandler,并对输出消息的格式进行设置,将其添加到 logger,然后将日志写入到指定的文件中,
import logging
logger = logging.getLogger(__name__)
logger.setLevel(level = logging.INFO)
handler = logging.FileHandler("log.txt")
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')handler.setFormatter(formatter)
logger.addHandler(handler)
logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
logger.info("Finish")
log.txt 中日志数据为,
2016-10-09 19:01:13,263 - __main__ - INFO - Start print log
2016-10-09 19:01:13,263 - __main__ - WARNING - Something maybe fail.
2016-10-09 19:01:13,263 - __main__ - INFO - Finish
2.2.2 将日志同时输出到屏幕和日志文件
logger 中添加 StreamHandler,可以将日志输出到屏幕上,
import logging
logger = logging.getLogger(__name__)
logger.setLevel(level = logging.INFO)
handler = logging.FileHandler("log.txt")
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')handler.setFormatter(formatter)
console = logging.StreamHandler()
console.setLevel(logging.INFO)
logger.addHandler(handler)
logger.addHandler(console)
logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
logger.info("Finish")
可以在 log.txt 文件和控制台中看到,
2016-10-09 19:20:46,553 - __main__ - INFO - Start print log
2016-10-09 19:20:46,553 - __main__ - WARNING - Something maybe fail.
2016-10-09 19:20:46,553 - __main__ - INFO - Finish
可以发现,logging 有一个日志处理的主对象,其他处理方式都是通过 addHandler 添加进去,logging 中包含的 handler 主要有如下几种,
handler名称:位置;作用
StreamHandler:logging.StreamHandler;日志输出到流,可以是sys.stderr,sys.stdout或者文件
FileHandler:logging.FileHandler;日志输出到文件
BaseRotatingHandler:logging.handlers.BaseRotatingHandler;基本的日志回滚方式
RotatingHandler:logging.handlers.RotatingHandler;日志回滚方式,支持日志文件最大数量和日志文件回滚
TimeRotatingHandler:logging.handlers.TimeRotatingHandler;日志回滚方式,在一定时间区域内回滚日志文件
SocketHandler:logging.handlers.SocketHandler;远程输出日志到TCP/IP sockets
DatagramHandler:logging.handlers.DatagramHandler;远程输出日志到UDP sockets
SMTPHandler:logging.handlers.SMTPHandler;远程输出日志到邮件地址
SysLogHandler:logging.handlers.SysLogHandler;日志输出到syslog
NTEventLogHandler:logging.handlers.NTEventLogHandler;远程输出日志到Windows NT/2000/XP的事件日志
MemoryHandler:logging.handlers.MemoryHandler;日志输出到内存中的指定buffer
HTTPHandler:logging.handlers.HTTPHandler;通过"GET"或者"POST"远程输出到HTTP服务器
2.2.3 日志回滚
使用 RotatingFileHandler,可以实现日志回滚,
import logging
from logging.handlers import RotatingFileHandler
logger = logging.getLogger(__name__)
logger.setLevel(level = logging.INFO)
#定义一个 RotatingFileHandler,最多备份 3 个日志文件,每个日志文件最大 1K
rHandler = RotatingFileHandler("log.txt",maxBytes = 1*1024,backupCount = 3)
rHandler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')rHandler.setFormatter(formatter)
console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setFormatter(formatter)
logger.addHandler(rHandler)
logger.addHandler(console)
logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
logger.info("Finish")
可以在工程目录中看到,备份的日志文件,
2016/10/09 19:36 732 log.txt
2016/10/09 19:36 967 log.txt.1
2016/10/09 19:36 985 log.txt.2
2016/10/09 19:36 976 log.txt.3
2.3 设置消息的等级
可以设置不同的日志等级,用于控制日志的输出,
日志等级:使用范围
FATAL:致命错误
CRITICAL:特别糟糕的事情,如内存耗尽、磁盘空间为空,一般很少使用
ERROR:发生错误时,如IO操作失败或者连接问题
WARNING:发生很重要的事件,但是并不是错误时,如用户登录密码错误
INFO:处理请求或者状态变化等日常事务
DEBUG:调试过程中使用DEBUG等级,如算法中每个循环的中间状态
2.4 捕获 traceback
Python 中的 traceback 模块被用于跟踪异常返回信息,可以在 logging 中记录下 traceback,
代码,
import logging
logger = logging.getLogger(__name__)
logger.setLevel(level = logging.INFO)
handler = logging.FileHandler("log.txt")
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')handler.setFormatter(formatter)
console = logging.StreamHandler()
console.setLevel(logging.INFO)
logger.addHandler(handler)
logger.addHandler(console)
logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
try:
open("sklearn.txt","rb")
except (SystemExit,KeyboardInterrupt):
raise
except Exception:
logger.error("Faild to open sklearn.txt from logger.error",exc_info = True)
logger.info("Finish")
控制台和日志文件 log.txt 中输出,
Start print log
Something maybe fail.
Faild to open sklearn.txt from logger.error
Traceback (most recent call last):
File "G:\zhb7627\Code\Eclipse WorkSpace\PythonTest\test.py", line 23, in <module>
open("sklearn.txt","rb")
IOError: [Errno 2] No such file or directory: 'sklearn.txt'
Finish
也可以使用 logger.exception(msg,_args),它等价于 logger.error(msg,exc_info = True,_args),
将
logger.error("Faild to open sklearn.txt from logger.error",exc_info = True)
替换为,
logger.exception("Failed to open sklearn.txt from logger.exception")
控制台和日志文件 log.txt 中输出,
Start print log
Something maybe fail.
Failed to open sklearn.txt from logger.exception
Traceback (most recent call last):
File "G:\zhb7627\Code\Eclipse WorkSpace\PythonTest\test.py", line 23, in <module>
open("sklearn.txt","rb")
IOError: [Errno 2] No such file or directory: 'sklearn.txt'
Finish
2.5 多模块使用 logging
主模块 mainModule.py,
import logging
import subModule
logger = logging.getLogger("mainModule")
logger.setLevel(level = logging.INFO)
handler = logging.FileHandler("log.txt")
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')handler.setFormatter(formatter)
console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setFormatter(formatter)
logger.addHandler(handler)
logger.addHandler(console)
logger.info("creating an instance of subModule.subModuleClass")
a = subModule.SubModuleClass()
logger.info("calling subModule.subModuleClass.doSomething")
a.doSomething()
logger.info("done with subModule.subModuleClass.doSomething")
logger.info("calling subModule.some_function")
subModule.som_function()
logger.info("done with subModule.some_function")
子模块 subModule.py,
import logging
module_logger = logging.getLogger("mainModule.sub")
class SubModuleClass(object):
def init(self):
self.logger = logging.getLogger("mainModule.sub.module")
self.logger.info("creating an instance in SubModuleClass")
def doSomething(self):
self.logger.info("do something in SubModule")
a = []
a.append(1)
self.logger.debug("list a =" + str(a))
self.logger.info("finish something in SubModuleClass")
def som_function():
module_logger.info("call function some_function")
执行之后,在控制和日志文件 log.txt 中输出,
2016-10-09 20:25:42,276 - mainModule - INFO - creating an instance of subModule.subModuleClass
2016-10-09 20:25:42,279 - mainModule.sub.module - INFO - creating an instance in SubModuleClass
2016-10-09 20:25:42,279 - mainModule - INFO - calling subModule.subModuleClass.doSomething
2016-10-09 20:25:42,279 - mainModule.sub.module - INFO - do something in SubModule
2016-10-09 20:25:42,279 - mainModule.sub.module - INFO - finish something in SubModuleClass
2016-10-09 20:25:42,279 - mainModule - INFO - done with subModule.subModuleClass.doSomething
2016-10-09 20:25:42,279 - mainModule - INFO - calling subModule.some_function
2016-10-09 20:25:42,279 - mainModule.sub - INFO - call function some_function
2016-10-09 20:25:42,279 - mainModule - INFO - done with subModule.some_function
首先在主模块定义了 logger'mainModule',并对它进行了配置,就可以在解释器进程里面的其他地方通过 getLogger('mainModule') 得到的对象都是一样的,不需要重新配置,可以直接使用。定义的该 logger 的子 logger,都可以共享父 logger 的定义和配置,所谓的父子 logger 是通过命名来识别,任意以 'mainModule' 开头的 logger 都是它的子 logger,例如 'mainModule.sub'。
实际开发一个 application,首先可以通过 logging 配置文件编写好这个 application 所对应的配置,可以生成一个根 logger,如 'PythonAPP',然后在主函数中通过 fileConfig 加载 logging 配置,接着在 application 的其他地方、不同的模块中,可以使用根 logger 的子 logger,如 'PythonAPP.Core','PythonAPP.Web' 来进行 log,而不需要反复的定义和配置各个模块的 logger。
3 通过 JSON 或者 YAML 文件配置 logging 模块
尽管可以在 Python 代码中配置 logging,但是这样并不够灵活,最好的方法是使用一个配置文件来配置。在 Python 2.7 及以后的版本中,可以从字典中加载 logging 配置,也就意味着可以通过 JSON 或者 YAML 文件加载日志的配置。
3.1 通过 JSON 文件配置
JSON 配置文件,
{
"version":1,
"disable_existing_loggers":false,
"formatters":{
"simple":{
"format":"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
}
},
"handlers":{
"console":{
"class":"logging.StreamHandler",
"level":"DEBUG",
"formatter":"simple",
"stream":"ext://sys.stdout"
},
"info_file_handler":{
"class":"logging.handlers.RotatingFileHandler",
"level":"INFO",
"formatter":"simple",
"filename":"info.log",
"maxBytes":"10485760",
"backupCount":20,
"encoding":"utf8"
},
"error_file_handler":{
"class":"logging.handlers.RotatingFileHandler",
"level":"ERROR",
"formatter":"simple",
"filename":"errors.log",
"maxBytes":10485760,
"backupCount":20,
"encoding":"utf8"
}
},
"loggers":{
"my_module":{
"level":"ERROR",
"handlers":["info_file_handler"],
"propagate":"no"
}
},
"root":{
"level":"INFO",
"handlers":["console","info_file_handler","error_file_handler"]
}
}
通过 JSON 加载配置文件,然后通过 logging.dictConfig 配置 logging,
import json
import logging.config
import os
def setup_logging(default_path = "logging.json",default_level = logging.INFO,env_key = "LOG_CFG"):
path = default_path
value = os.getenv(env_key,None)
if value:
path = value
if os.path.exists(path):
with open(path,"r") as f:
config = json.load(f)
logging.config.dictConfig(config)
else:
logging.basicConfig(level = default_level)
def func():
logging.info("start func")
logging.info("exec func")
logging.info("end func")
if name == "main":
setup_logging(default_path = "logging.json")
func()
3.2 通过 YAML 文件配置
通过 YAML 文件进行配置,比 JSON 看起来更加简介明了,
version: 1
disable_existing_loggers: False
formatters:
simple:
format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
handlers:
console:
class: logging.StreamHandler
level: DEBUG
formatter: simple
stream: ext://sys.stdout
info_file_handler:
class: logging.handlers.RotatingFileHandler
level: INFO
formatter: simple
filename: info.log
maxBytes: 10485760
backupCount: 20
encoding: utf8
error_file_handler:
class: logging.handlers.RotatingFileHandler
level: ERROR
formatter: simple
filename: errors.log
maxBytes: 10485760
backupCount: 20
encoding: utf8
loggers:
my_module:
level: ERROR
handlers: [info_file_handler]
propagate: no
root:
level: INFO
handlers: [console,info_file_handler,error_file_handler]
通过 YAML 加载配置文件,然后通过 logging.dictConfig 配置 logging,
import yaml
import logging.config
import os
def setup_logging(default_path = "logging.yaml",default_level = logging.INFO,env_key = "LOG_CFG"):
path = default_path
value = os.getenv(env_key,None)
if value:
path = value
if os.path.exists(path):
with open(path,"r") as f:
config = yaml.load(f)
logging.config.dictConfig(config)
else:
logging.basicConfig(level = default_level)
def func():
logging.info("start func")
logging.info("exec func")
logging.info("end func")
if name == "main":
setup_logging(default_path = "logging.yaml")
func()
subprocess 模块
subprocess 是 Python 2.4 中新增的一个模块,它允许你生成新的进程,连接到它们的 input/output/error 管道,并获取它们的返回(状态)码。这个模块的目的在于替换几个旧的模块和方法,如:
- os.system
- os.spawn*
1. subprocess 模块中的常用函数
函数 描述
subprocess.run()
Python 3.5 中新增的函数。执行指定的命令,等待命令执行完成后返回一个包含执行结果的 CompletedProcess 类的实例。
subprocess.call()
执行指定的命令,返回命令执行状态,其功能类似于 os.system(cmd)。
subprocess.check_call()
Python 2.5 中新增的函数。 执行指定的命令,如果执行成功则返回状态码,否则抛出异常。其功能等价于 subprocess.run(..., check=True)。
subprocess.check_output()
Python 2.7 中新增的的函数。执行指定的命令,如果执行状态码为 0 则返回命令执行结果,否则抛出异常。
subprocess.getoutput(cmd)
接收字符串格式的命令,执行命令并返回执行结果,其功能类似于 os.popen(cmd).read()和 commands.getoutput(cmd)。
subprocess.getstatusoutput(cmd)
执行 cmd 命令,返回一个元组 (命令执行状态, 命令执行结果输出),其功能类似于 commands.getstatusoutput()。
说明:
- 在 Python 3.5 之后的版本中,官方文档中提倡通过 subprocess.run() 函数替代其他函数来使用 subproccess 模块的功能;
- 在 Python 3.5 之前的版本中,我们可以通过 subprocess.call(),subprocess.getoutput() 等上面列出的其他函数来使用 subprocess 模块的功能;
- subprocess.run()、subprocess.call()、subprocess.check_call()和 subprocess.check_output() 都是通过对 subprocess.Popen 的封装来实现的高级函数,因此如果我们需要更复杂功能时,可以通过 subprocess.Popen 来完成。
- subprocess.getoutput()和 subprocess.getstatusoutput() 函数是来自 Python 2.x 的 commands 模块的两个遗留函数。它们隐式的调用系统 shell,并且不保证其他函数所具有的安全性和异常处理的一致性。另外,它们从 Python 3.3.4 开始才支持 Windows 平台。
2. 上面各函数的定义及参数说明
函数参数列表:
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, timeout=None, check=False, universal_newlines=False)
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)
subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)
subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False, timeout=None)
subprocess.getstatusoutput(cmd)
subprocess.getoutput(cmd)
参数说明:
- args: 要执行的 shell 命令,默认应该是一个字符串序列,如 ['df', '-Th'] 或('df', '-Th'),也可以是一个字符串,如 'df -Th',但是此时需要把 shell 参数的值置为 True。
- shell: 如果 shell 为 True,那么指定的命令将通过 shell 执行。如果我们需要访问某些 shell 的特性,如管道、文件名通配符、环境变量扩展功能,这将是非常有用的。当然,python 本身也提供了许多类似 shell 的特性的实现,如 glob、fnmatch、os.walk()、os.path.expandvars()、os.expanduser() 和 shutil 等。
- check: 如果 check 参数的值是 True,且执行命令的进程以非 0 状态码退出,则会抛出一个 CalledProcessError 的异常,且该异常对象会包含 参数、退出状态码、以及 stdout 和 stderr(如果它们有被捕获的话)。
- stdout, stderr:
- run() 函数默认不会捕获命令执行结果的正常输出和错误输出,如果我们向获取这些内容需要传递 subprocess.PIPE,然后可以通过返回的 CompletedProcess 类实例的 stdout 和 stderr 属性或捕获相应的内容;
- call()和 check_call() 函数返回的是命令执行的状态码,而不是 CompletedProcess 类实例,所以对于它们而言,stdout 和 stderr 不适合赋值为 subprocess.PIPE;
- check_output() 函数默认就会返回命令执行结果,所以不用设置 stdout 的值,如果我们希望在结果中捕获错误信息,可以执行 stderr=subprocess.STDOUT。
- input: 该参数是传递给 Popen.communicate(),通常该参数的值必须是一个字节序列,如果 universal_newlines=True,则其值应该是一个字符串。
- universal_newlines: 该参数影响的是输入与输出的数据格式,比如它的值默认为 False,此时 stdout 和 stderr 的输出是字节序列;当该参数的值设置为 True 时,stdout 和 stderr 的输出是字符串。
3. subprocess.CompletedProcess 类介绍
需要说明的是,subprocess.run() 函数是 Python3.5 中新增的一个高级函数,其返回值是一个 subprocess.CompletedPorcess 类的实例,因此,subprocess.completedPorcess 类也是 Python 3.5 中才存在的。它表示的是一个已结束进程的状态信息,它所包含的属性如下:
- args: 用于加载该进程的参数,这可能是一个列表或一个字符串
- returncode: 子进程的退出状态码。通常情况下,退出状态码为 0 则表示进程成功运行了;一个负值 -N 表示这个子进程被信号 N 终止了
- stdout: 从子进程捕获的 stdout。这通常是一个字节序列,如果 run()函数被调用时指定 universal_newlines=True,则该属性值是一个字符串。如果 run() 函数被调用时指定 stderr=subprocess.STDOUT,那么 stdout 和 stderr 将会被整合到这一个属性中,且 stderr 将会为 None
- stderr: 从子进程捕获的 stderr。它的值与 stdout 一样,是一个字节序列或一个字符串。如果 stderr 灭有被捕获的话,它的值就为 None
- check_returncode(): 如果 returncode 是一个非 0 值,则该方法会抛出一个 CalledProcessError 异常。
4. 实例
subprocess.run()
>>> subprocess.run(["ls", "-l"]) # doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0)
>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1
>>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0,
stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n')
subprocess.call()
>>> subprocess.call(['ls', '-l'])
总用量 160
drwxr-xr-x 2 wader wader 4096 12月 7 2015 公共的
drwxr-xr-x 2 wader wader 4096 12月 7 2015 模板
drwxr-xr-x 2 wader wader 4096 12月 7 2015 视频
drwxr-xr-x 2 wader wader 4096 12月 7 2015 图片
drwxr-xr-x 2 wader wader 4096 12月 7 2015 文档
drwxr-xr-x 2 wader wader 4096 4月 13 2016 下载
drwxr-xr-x 2 wader wader 4096 12月 7 2015 音乐
drwxr-xr-x 7 wader wader 4096 5月 26 2016 桌面
0
>>> subprocess.call('ls -l', shell=True)
总用量 160
drwxr-xr-x 2 wader wader 4096 12月 7 2015 公共的
drwxr-xr-x 2 wader wader 4096 12月 7 2015 模板
drwxr-xr-x 2 wader wader 4096 12月 7 2015 视频
drwxr-xr-x 2 wader wader 4096 12月 7 2015 图片
drwxr-xr-x 2 wader wader 4096 12月 7 2015 文档
drwxr-xr-x 2 wader wader 4096 4月 13 2016 下载
drwxr-xr-x 2 wader wader 4096 12月 7 2015 音乐
drwxr-xr-x 7 wader wader 4096 5月 26 2016 桌面
0
>>> subprocess.call(['ls', '-l'], stdout=subprocess.DEVNULL)
0
>>> subprocess.call(['ls', '-l', '/test'])
ls: 无法访问/test: 没有那个文件或目录
2
suprocess.check_call()
>>> subprocess.check_call(['ls', '-l'])
总用量 160
drwxr-xr-x 2 wader wader 4096 12月 7 2015 公共的
drwxr-xr-x 2 wader wader 4096 12月 7 2015 模板
drwxr-xr-x 2 wader wader 4096 12月 7 2015 视频
drwxr-xr-x 2 wader wader 4096 12月 7 2015 图片
drwxr-xr-x 2 wader wader 4096 12月 7 2015 文档
drwxr-xr-x 2 wader wader 4096 4月 13 2016 下载
drwxr-xr-x 2 wader wader 4096 12月 7 2015 音乐
drwxr-xr-x 7 wader wader 4096 5月 26 2016 桌面
0
>>> subprocess.check_call('ls -l', shell=True)
总用量 160
drwxr-xr-x 2 wader wader 4096 12月 7 2015 公共的
drwxr-xr-x 2 wader wader 4096 12月 7 2015 模板
drwxr-xr-x 2 wader wader 4096 12月 7 2015 视频
drwxr-xr-x 2 wader wader 4096 12月 7 2015 图片
drwxr-xr-x 2 wader wader 4096 12月 7 2015 文档
drwxr-xr-x 2 wader wader 4096 4月 13 2016 下载
drwxr-xr-x 2 wader wader 4096 12月 7 2015 音乐
drwxr-xr-x 7 wader wader 4096 5月 26 2016 桌面
0
>>> subprocess.check_call('ls -l /test', shell=True)
ls: 无法访问/test: 没有那个文件或目录
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.4/subprocess.py", line 557, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command 'ls -l /test' returned non-zero exit status 2
sbuprocess.check_output()
>>> ret = subprocess.check_output(['ls', '-l'])
>>> print(ret)
b'\xe5\x85\xac\xe5\x85\xb1\xe7\x9a\x84\ndrwxr-xr-x 2 wader wader 4096 12\xe6\x9c\x88 7 2015 \xe6\xa8\xa1\xe6\x9d\xbf\ndrwxr-xr-x 2 wader wader 4096 12\xe6\x9c\x88 7 2015 \xe8\xa7\x86\xe9\xa2\x91\ndrwxr-xr-x 2 wader wader 4096 12\xe6\x9c\x88 7 2015 \xe5\x9b\xbe\xe7\x89\x87\ndrwxr-xr-x 2 wader wader 4096 12\xe6\x9c\x88 7 2015 \xe6\x96\x87\xe6\xa1\xa3\ndrwxr-xr-x 2 wader wader 4096 4\xe6\x9c\x88 13 2016 \xe4\xb8\x8b\xe8\xbd\xbd\ndrwxr-xr-x 2 wader wader 4096 12\xe6\x9c\x88 7 2015 \xe9\x9f\xb3\xe4\xb9\x90\ndrwxr-xr-x 7 wader wader 4096 5\xe6\x9c\x88 26 2016 \xe6\xa1\x8c\xe9\x9d\xa2\n'
>>> ret = subprocess.check_output(['ls', '-l'], universal_newlines=True)
>>> print(ret)
总用量 160
drwxr-xr-x 2 wader wader 4096 12月 7 2015 公共的
drwxr-xr-x 2 wader wader 4096 12月 7 2015 模板
drwxr-xr-x 2 wader wader 4096 12月 7 2015 视频
drwxr-xr-x 2 wader wader 4096 12月 7 2015 图片
drwxr-xr-x 2 wader wader 4096 12月 7 2015 文档
drwxr-xr-x 2 wader wader 4096 4月 13 2016 下载
drwxr-xr-x 2 wader wader 4096 12月 7 2015 音乐
drwxr-xr-x 7 wader wader 4096 5月 26 2016 桌面
subprocess.getoutput()与 subprocess.getstatusoutput()
>>> ret = subprocess.getoutput('ls -l')
>>> print(ret)
总用量 160
drwxr-xr-x 2 wader wader 4096 12月 7 2015 公共的
drwxr-xr-x 2 wader wader 4096 12月 7 2015 模板
drwxr-xr-x 2 wader wader 4096 12月 7 2015 视频
drwxr-xr-x 2 wader wader 4096 12月 7 2015 图片
drwxr-xr-x 2 wader wader 4096 12月 7 2015 文档
drwxr-xr-x 2 wader wader 4096 4月 13 2016 下载
drwxr-xr-x 2 wader wader 4096 12月 7 2015 音乐
drwxr-xr-x 7 wader wader 4096 5月 26 2016 桌面
>>> retcode, output = subprocess.getstatusoutput('ls -l')
>>> print(retcode)
0
>>> print(output)
总用量 160
drwxr-xr-x 2 wader wader 4096 12月 7 2015 公共的
drwxr-xr-x 2 wader wader 4096 12月 7 2015 模板
drwxr-xr-x 2 wader wader 4096 12月 7 2015 视频
drwxr-xr-x 2 wader wader 4096 12月 7 2015 图片
drwxr-xr-x 2 wader wader 4096 12月 7 2015 文档
drwxr-xr-x 2 wader wader 4096 4月 13 2016 下载
drwxr-xr-x 2 wader wader 4096 12月 7 2015 音乐
drwxr-xr-x 7 wader wader 4096 5月 26 2016 桌面
>>> retcode, output = subprocess.getstatusoutput('ls -l /test')
>>> print(retcode)
2
>>> print(output)
ls: 无法访问/test: 没有那个文件或目录
三、subprocess.Popen 介绍
该类用于在一个新的进程中执行一个子程序。前面我们提到过,上面介绍的这些函数都是基于 subprocess.Popen 类实现的,通过使用这些被封装后的高级函数可以很方面的完成一些常见的需求。由于 subprocess 模块底层的进程创建和管理是由 Popen 类来处理的,因此,当我们无法通过上面哪些高级函数来实现一些不太常见的功能时就可以通过 subprocess.Popen 类提供的灵活的 api 来完成。
1.subprocess.Popen 的构造函数
class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None,
preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False,
startup_info=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=())
参数说明:
- args: 要执行的 shell 命令,可以是字符串,也可以是命令各个参数组成的序列。当该参数的值是一个字符串时,该命令的解释过程是与平台相关的,因此通常建议将 args 参数作为一个序列传递。
- bufsize: 指定缓存策略,0 表示不缓冲,1 表示行缓冲,其他大于 1 的数字表示缓冲区大小,负数 表示使用系统默认缓冲策略。
- stdin, stdout, stderr: 分别表示程序标准输入、输出、错误句柄。
- preexec_fn: 用于指定一个将在子进程运行之前被调用的可执行对象,只在 Unix 平台下有效。
- close_fds: 如果该参数的值为 True,则除了 0,1 和 2 之外的所有文件描述符都将会在子进程执行之前被关闭。
- shell: 该参数用于标识是否使用 shell 作为要执行的程序,如果 shell 值为 True,则建议将 args 参数作为一个字符串传递而不要作为一个序列传递。
- cwd: 如果该参数值不是 None,则该函数将会在执行这个子进程之前改变当前工作目录。
- env: 用于指定子进程的环境变量,如果 env=None,那么子进程的环境变量将从父进程中继承。如果 env!=None,它的值必须是一个映射对象。
- universal_newlines: 如果该参数值为 True,则该文件对象的 stdin,stdout 和 stderr 将会作为文本流被打开,否则他们将会被作为二进制流被打开。
- startupinfo 和 creationflags: 这两个参数只在 Windows 下有效,它们将被传递给底层的 CreateProcess() 函数,用于设置子进程的一些属性,如主窗口的外观,进程优先级等。
2. subprocess.Popen 类的实例可调用的方法
方法 描述
Popen.poll()
用于检查子进程(命令)是否已经执行结束,没结束返回 None,结束后返回状态码。
Popen.wait(timeout=None)
等待子进程结束,并返回状态码;如果在 timeout 指定的秒数之后进程还没有结束,将会抛出一个 TimeoutExpired 异常。
Popen.communicate(input=None, timeout=None)
该方法可用来与进程进行交互,比如发送数据到 stdin,从 stdout 和 stderr 读取数据,直到到达文件末尾。
Popen.send_signal(signal)
发送指定的信号给这个子进程。
Popen.terminate()
停止该子进程。
Popen.kill()
杀死该子进程。
关于 communicate() 方法的说明:
- 该方法中的可选参数 input 应该是将被发送给子进程的数据,或者如没有数据发送给子进程,该参数应该是 None。input 参数的数据类型必须是字节串,如果 universal_newlines 参数值为 True,则 input 参数的数据类型必须是字符串。
- 该方法返回一个元组 (stdout_data, stderr_data),这些数据将会是字节穿或字符串(如果 universal_newlines 的值为 True)。
- 如果在 timeout 指定的秒数后该进程还没有结束,将会抛出一个 TimeoutExpired 异常。捕获这个异常,然后重新尝试通信不会丢失任何输出的数据。但是超时之后子进程并没有被杀死,为了合理的清除相应的内容,一个好的应用应该手动杀死这个子进程来结束通信。
- 需要注意的是,这里读取的数据是缓冲在内存中的,所以,如果数据大小非常大或者是无限的,就不应该使用这个方法。
3. subprocess.Popen 使用实例
实例 1:
>>> import subprocess
>>>
>>> p = subprocess.Popen('df -Th', stdout=subprocess.PIPE, shell=True)
>>> print(p.stdout.read())
Filesystem Type Size Used Avail Use% Mounted on
/dev/vda1 ext4 40G 12G 26G 31% /
devtmpfs devtmpfs 3.9G 0 3.9G 0% /dev
tmpfs tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs tmpfs 3.9G 386M 3.5G 10% /run
tmpfs tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
tmpfs tmpfs 783M 0 783M 0% /run/user/0
tmpfs tmpfs 783M 0 783M 0% /run/user/1000
实例 2:
>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> obj.stdin.write('print(1) \n')
>>> obj.stdin.write('print(2) \n')
>>> obj.stdin.write('print(3) \n')
>>> out,err = obj.communicate()
>>> print(out)
1
2
3
>>> print(err)
实例 3:
>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> out,err = obj.communicate(input='print(1) \n')
>>> print(out)
1
>>> print(err)
实例 4:
实现类似df -Th | grep data
命令的功能,实际上就是实现 shell 中管道的共功能。
>>>
>>> p1 = subprocess.Popen(['df', '-Th'], stdout=subprocess.PIPE)
>>> p2 = subprocess.Popen(['grep', 'data'], stdin=p1.stdout, stdout=subprocess.PIPE)
>>> out,err = p2.communicate()
>>> print(out)
/dev/vdb1 ext4 493G 4.8G 463G 2% /data
/dev/vdd1 ext4 1008G 420G 537G 44% /data1
/dev/vde1 ext4 985G 503G 432G 54% /data2
>>> print(err)
None
四、总结
那么我们到底该用哪个模块、哪个函数来执行命令与系统及系统进行交互呢?下面我们来做个总结:
- 首先应该知道的是,Python2.4 版本引入了 subprocess 模块用来替换 os.system()、os.popen()、os.spawn*() 等函数以及 commands 模块;也就是说如果你使用的是 Python 2.4 及以上的版本就应该使用 subprocess 模块了。
- 如果你的应用使用的 Python 2.4 以上,但是是 Python 3.5 以下的版本,Python 官方给出的建议是使用 subprocess.call()函数。Python 2.5 中新增了一个 subprocess.check_call() 函数,Python 2.7 中新增了一个 subprocess.check_output() 函数,这两个函数也可以按照需求进行使用。
- 如果你的应用使用的是 Python 3.5 及以上的版本(目前应该还很少),Python 官方给出的建议是尽量使用 subprocess.run() 函数。
- 当 subprocess.call()、subprocess.check_call()、subprocess.check_output()和 subprocess.run() 这些高级函数无法满足需求时,我们可以使用 subprocess.Popen 类来实现我们需要的复杂功能。
json ,pickle 模块
JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。JSON 的数据格式其实就是 python 里面的字典格式,里面可以包含方括号括起来的数组,也就是 python 里面的列表。
在 python 中,有专门处理 json 格式的模块—— json 和 picle 模块
Json 模块提供了四个方法: dumps、dump、loads、load
pickle 模块也提供了四个功能:dumps、dump、loads、load
一. dumps 和 dump:
dumps 和 dump 序列化方法
dumps 只完成了序列化为 str,
dump 必须传文件描述符,将序列化的 str 保存到文件中
查看源码:
def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
allow_nan=True, cls=None, indent=None, separators=None,
default=None, sort_keys=False, **kw):
# Serialize ``obj`` to a JSON formatted ``str``.
# 序列号 “obj” 数据类型 转换为 JSON 格式的字符串
def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
allow_nan=True, cls=None, indent=None, separators=None,
default=None, sort_keys=False, **kw):
"""Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
``.write()``-supporting file-like object).
我理解为两个动作,一个动作是将”obj“转换为 JSON 格式的字符串,还有一个动作是将字符串写入到文件中,也就是说文件描述符 fp 是必须要的参数 """
示例代码:
>>> import json
>>> json.dumps([]) # dumps 可以格式化所有的基本数据类型为字符串
'[]'
>>> json.dumps(1) # 数字
'1'
>>> json.dumps('1') # 字符串
'"1"'
>>> dict = {"name":"Tom", "age":23}
>>> json.dumps(dict) # 字典
'{"name": "Tom", "age": 23}'
a = {"name":"Tom", "age":23}
with open("test.json", "w", encoding='utf-8') as f:
# indent 超级好用,格式化保存字典,默认为 None,小于 0 为零个空格
f.write(json.dumps(a, indent=4))
# json.dump(a,f,indent=4) # 和上面的效果一样
保存的文件效果:

二. loads 和 load
loads 和 load 反序列化方法
loads 只完成了反序列化,
load 只接收文件描述符,完成了读取文件和反序列化
查看源码:
def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):
"""Deserialize ``s`` (a ``str`` instance containing a JSON document) to a Python object.
将包含 str 类型的 JSON 文档反序列化为一个 python 对象"""
def load(fp, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):
"""Deserialize ``fp`` (a ``.read()``-supporting file-like object containing a JSON document) to a Python object.
将一个包含 JSON 格式数据的可读文件饭序列化为一个 python 对象"""
实例:
>>> json.loads('{"name":"Tom", "age":23}')
{'age': 23, 'name': 'Tom'}
import json
with open("test.json", "r", encoding='utf-8') as f:
aa = json.loads(f.read())
f.seek(0)
bb = json.load(f) # 与 json.loads(f.read())
print(aa)
print(bb)
# 输出:
{'name': 'Tom', 'age': 23}
{'name': 'Tom', 'age': 23}
三. json 和 pickle 模块
json 模块和 pickle 模块都有 dumps、dump、loads、load 四种方法,而且用法一样。
不用的是 json 模块序列化出来的是通用格式,其它编程语言都认识,就是普通的字符串,
而 picle 模块序列化出来的只有 python 可以认识,其他编程语言不认识的,表现为乱码
不过 picle 可以序列化函数,但是其他文件想用该函数,在该文件中需要有该文件的定义(定义和参数必须相同,内容可以不同)
四. python 对象(obj) 与 json 对象的对应关系
+-------------------+---------------+
| Python | JSON |
+===================+===============+
| dict | object |
+-------------------+---------------+
| list, tuple | array |
+-------------------+---------------+
| str | string |
+-------------------+---------------+
| int, float | number |
+-------------------+---------------+
| True | true |
+-------------------+---------------+
| False | false |
+-------------------+---------------+
| None | null |
+-------------------+---------------+
五. 总结
1. json 序列化方法:
dumps:无文件操作 dump:序列化 + 写入文件
2. json 反序列化方法:
loads:无文件操作 load: 读文件 + 反序列化
3. json 模块序列化的数据 更通用
picle 模块序列化的数据 仅 python 可用,但功能强大,可以序列号函数
4. json 模块可以序列化和反序列化的 数据类型 见 python 对象(obj) 与 json 对象的对应关系表
5. 格式化写入文件利用 indent = 4
ElementTree 是 python 的 XML 处理模块
ElementTree 是 python 的 XML 处理模块,它提供了一个轻量级的对象模型。它在 Python2.5 以后成为 Python 标准库的一部分,但是 Python2.4 之前需要单独安装。在使用 ElementTree 模块时,需要 import xml.etree.ElementTree 的操作。
ElementTree 表示整个 XML 节点树,而 Element 表示节点数中的一个单独的节点。
构建
ElementTree(tag),其中 tag 表示根节点,初始化一个 ElementTree 对象。
Element(tag, attrib={}, **extra) 函数用来构造 XML 的一个根节点,其中 tag 表示根节点的名称,attrib 是一个可选项,表示节点的属性。
SubElement(parent, tag, attrib={}, **extra) 用来构造一个已经存在的节点的子节点
Element.text 和 SubElement.text 表示 element 对象的额外的内容属性,Element.tag 和 Element.attrib 分别表示 element 对象的标签和属性。
ElementTree.write(file, encoding='us-ascii', xml_declaration=None,
default_namespace=None, method='xml'),函数新建一个 XML 文件,并且将节点数数据写入 XML 文件中。
#encoding=utf-8
import xml.etree.ElementTree as ET
#新建 xml 文件
def buildNewsXmlFile():
#设置一个新节点,并设置其标签为 root
root = ET.Element("root")
#在root下新建两个子节点,设置其名称分别为sina和chinabyte
sina = ET.SubElement(root, "sina")
chinabyte = ET.SubElement(root, "chinabyte")
#在sina下新建两个子节点,设置其节点名称分别为number和first
sina_number = ET.SubElement(sina, "number")
sina_number.text = "1"
sina_first = ET.SubElement(sina, "first")
sina_first.text = "http://roll.tech.sina.com.cn/internet_all/index_1.shtml"
#在chinabyte下新建两个子节点,设置其节点名称为number和first
chinabyte_number = ET.SubElement(chinabyte, "number")
chinabyte_number.text = "1"
chinabyte_first = ET.SubElement(chinabyte, "first")
chinabyte_first.text = "http://www.chinabyte.com/more/124566.shtml"
#将节点数信息保存在ElementTree中,并且保存为XML格式文件
tree = ET.ElementTree(root)
tree.write("urlfile.xml")</pre>
解析和修改 XML 文件
ElementTree.parse(source, parser=None),将 xml 文件加载并返回 ElementTree 对象。parser 是一个可选的参数,如果为空,则默认使用标准的 XMLParser 解析器。
ElementTree.getroot(),得到根节点。返回根节点的 element 对象。
Element.remove(tag),删除 root 下名称为 tag 的子节点
以下函数,ElementTree 和 Element 的对象都包含。
find(match),得到第一个匹配 match 的子节点,match 可以是一个标签名称或者是路径。返回个 element
findtext(match,default=None),得到第一个配置的 match 的 element 的内容
findall(match),得到匹配 match 下的所有的子节点,match 可以是一个标签或者是路径,它会返回一个 list,包含匹配的 elements 的信息
iter(tag),创建一个以当前节点为根节点的 iterator。
这里有一个 xml 文件
<?xml version="1.0"?>
<data>
<country name="Liechtenstein">
<rank>1</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore">
<rank>4</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
<country name="Panama">
<rank>68</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</country>
</data>
现在是解析 xml 文件的代码
#解析 Xml 文件
def parseXmlFile(xml_name):
#将 XMl 文件加载并返回一个 ELementTree 对象
tree = ET.parse(xml_name)
#得到第一个匹配sina标签的Element对象
sina = tree.find("contry")
#得到sina的SubElement
for sub_tag in sina:
print sub_tag.text
#得到所有匹配sina标签的Element对象的list集合
list_contry = tree.findall("contry")
for contry in list_contry:
for sub_tag in contry:
print sub_tag.text
#修改xml文件
for rank in tree.iter('rank')
new_rank = int(rank.text)+1
rank.text = str(new_rank)
rank.set('updated', 'yes')
tree.write(xml_name)
第一次的输出是:1,2008,14100
第二次的输出是:1,2008,14100,4,2011,59900,68,2011,13600
修改后的 xml 文件为
<?xml version="1.0"?>
<data>
<country name="Liechtenstein">
<rank updated="yes">2</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore">
<rank updated="yes">5</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
<country name="Panama">
<rank updated="yes">69</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</country>
</data>
configparser 简介
configparser 是 Pyhton 标准库中用来解析配置文件的模块,并且内置方法和字典非常接近。Python2.x 中名为 ConfigParser,3.x 已更名小写,并加入了一些新功能。
配置文件的格式如下:
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
[bitbucket.org]
User = Tom
[topsecret.com]
Port: 50022
ForwardX11: no
“[ ]”包含的为 section,section 下面为类似于 key - value 的配置内容;
configparser 默认支持 ‘=’ ‘:’ 两种分隔。
configparser 常用方法
初始化实例
使用 configparser 首先需要初始化实例,并读取配置文件:
>>> import configparser
>>> config = configparser.ConfigParser() # 注意大小写
>>> config.read("config.ini") # 配置文件的路径
["config.ini"]
或者可以直接读字典
>>> parser = configparser.ConfigParser()
>>> parser.read_dict({'section1': {'key1': 'value1',
... 'key2': 'value2',
... 'key3': 'value3'},
... 'section2': {'keyA': 'valueA',
... 'keyB': 'valueB',
... 'keyC': 'valueC'},
... 'section3': {'foo': 'x',
... 'bar': 'y',
... 'baz': 'z'}
... })
获取所有 sections
>>> config.sections()
['bitbucket.org', 'topsecret.com'] # 注意会过滤掉 [DEFAULT]
获取指定 section 的 keys & values
>>> config.items('topsecret.com')
>>>> [('port', '50022'), ('forwardx11', 'no')] # 注意 items() 返回的字符串会全变成小写
获取指定 section 的 keys
>>> config.options('topsecret.com')
['Port', 'ForwardX11']
>>> for option in config['topsecret.com']:
... print(option)
Port
ForwardX11
获取指定 key 的 value
>>> config['bitbucket.org']['User']
'Tom'
>>> config.get('bitbucket.org', 'User')
'Tom'
>>> config.getint('topsecret.com', 'Port')
50022
检查
>>> 'DEFAULT' in config
True
>>> 'test' in config['section_test']
False
>>> 'Tom' in config['bitbucket.org']['User']
True
>>> config.has_section('bitbucket.org')
True
>>> config.has_option('section_test', 'test')
False
添加
>>> config.add_section('Section_1')
>>> config.set('Section_1', 'key_1', 'value_1') # 注意键值是用 set() 方法
>>> config.write(open('config.ini', 'w')) # 一定要写入才生效
删除
>>> config.remove_option('Section_1', 'key_1')
True
>>> config.remove_section('Section_1')
True
>>> config.clear() # 清空除 [DEFAULT] 之外所有内容
>>> config.write(open('config.ini', 'w'))
关于 [DEFAULT]
[DEFAULT] 一般包含 ini 格式配置文件的默认项,所以 configparser 部分方法会自动跳过这个 section 。
前面已经提到 sections()是获取不到的,还有删除方法对 [DEFAULT] 也无效:
>>> config.remove_section('DEFAULT')
False
>>> config.clear()
>>> 'DEFAULT' in config
True
>>> 'ForwardX11' in config['DEFAULT']
True
>>> config.sections()
[]
但指定删除和修改 [DEFAULT] 里的 keys & values 是可以的:
>>> config.remove_option('DEFAULT', 'ForwardX11')
True
>>> config.set('DEFAULT', 'ForwardX11','no')
>>> config['DEFAULT']['ForwardX11']
'no'
还有个特殊的是,has_section() 也无效,可以和 in 区别使用
>>> config.has_section('DEFAULT')
False
>>> 'DEFAULT' in config
True
更多用法请看官方文档:https://docs.python.org/3.6/library/configparser.html
randmon(获取随机数)
random.random
random.random() 用于生成一个 0 到 1 的随机符点数: 0 <= n < 1.0
random.uniform
random.uniform(a, b),用于生成一个指定范围内的随机符点数,两个参数其中一个是上限,一个是下限。如果 a > b,则生成的随机数 n: a <= n <= b。如果 a <b, 则 b <= n <= a
print random.uniform(10, 20)
print random.uniform(20, 10)
# 18.7356606526
# 12.5798298022
random.randint
random.randint(a, b),用于生成一个指定范围内的整数。其中参数 a 是下限,参数 b 是上限,生成的随机数 n: a <= n <= b
print random.randint(12, 20) # 生成的随机数 n: 12 <= n <= 20
print random.randint(20, 20) # 结果永远是 20
# print random.randint(20, 10) # 该语句是错误的。下限必须小于上限
random.randrange
random.randrange([start], stop[,
step]),从指定范围内,按指定基数递增的集合中 获取一个随机数。如:random.randrange(10, 100,
2),结果相当于从 [10, 12, 14, 16, ... 96, 98] 序列中获取一个随机数。random.randrange(10,
100, 2)在结果上与 random.choice(range(10, 100, 2) 等效
random.choice
random.choice 从序列中获取一个随机元素。其函数原型为:random.choice(sequence)。参数 sequence 表示一个有序类型。这里要说明
一下:sequence 在 python 不是一种特定的类型,而是泛指一系列的类型。list, tuple,
字符串都属于 sequence。有关 sequence 可以查看 python 手册数据模型这一章。下面是使用 choice 的一些例子:
print random.choice("学习 Python")
print random.choice(["JGood", "is", "a", "handsome", "boy"])
print random.choice(("Tuple", "List", "Dict"))
random.shuffle
random.shuffle(x[, random]),用于将一个列表中的元素打乱。如:
p = ["Python", "is", "powerful", "simple", "and so on..."]
random.shuffle(p)
print p
# ['powerful', 'simple', 'is', 'Python', 'and so on...']
random.sample
random.sample(sequence, k),从指定序列中随机获取指定长度的片断。sample 函数不会修改原有序列
list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
slice = random.sample(list, 5) # 从 list 中随机获取 5 个元素,作为一个片断返回
print slice
print list # 原有序列并没有改变
随机整数:
>>> import random
>>> random.randint(0,99)
# 21
随机选取 0 到 100 间的偶数:
>>> import random
>>> random.randrange(0, 101, 2)
# 42
随机浮点数:
>>> import random
>>> random.random()
0.85415370477785668
>>> random.uniform(1, 10)
# 5.4221167969800881
随机字符:
>>> import random
>>> random.choice('abcdefg&#%^*f')
# 'd'
多个字符中选取特定数量的字符:
>>> import random
random.sample('abcdefghij', 3)
# ['a', 'd', 'b']
多个字符中选取特定数量的字符组成新字符串:
>>> import random
>>> import string
>>> string.join(random.sample(['a','b','c','d','e','f','g','h','i','j'], 3)).replace("","")
# 'fih'
随机选取字符串:
>>> import random
>>> random.choice (['apple', 'pear', 'peach', 'orange', 'lemon'] )
# 'lemon'
洗牌:
>>> import random
>>> items = [1, 2, 3, 4, 5, 6]
>>> random.shuffle(items)
>>> items
# [3, 2, 5, 6, 4, 1]
shutil 模块
引入: import shutil
copy()
功能:复制文件
格式:shutil.copy('来源文件','目标地址')
返回值:复制之后的路径
copy2()
功能:复制文件,保留元数据
格式:shutil.copy2('来源文件','目标地址')
返回值:复制之后的路径
copyfileobj()
将一个文件的内容拷贝的另外一个文件当中
格式:shutil.copyfileobj(open(来源文件,'r'),open('目标文件','w'))
返回值:无
copyfile()
功能:将一个文件的内容拷贝的另外一个文件当中
格式:shutil.copyfile(来源文件,目标文件)
返回值:目标文件的路径
copytree()
功能:复制整个文件目录
格式:shutil.copytree(来源目录,目标目录)
返回值:目标目录的路径
注意:无论文件夹是否为空,均可以复制,而且会复制文件夹中的所有内容
copymode()
功能:拷贝权限
copystat()
功能:拷贝元数据(状态)
rmtree()
功能:移除整个目录,无论是否空
格式:shutil.rmtree(目录路径)
返回值:无
move()
功能:移动文件或者文件夹
格式:shutil.move(来源地址,目标地址)
返回值:目标地址
which()
功能:检测命令对应的文件路径
格式:shutil.which(‘命令字符串’)
返回值:命令文件所在位置
注意:window和linux不太一样。 window的命令都是.exe结尾,linux则不是
disk_usage()
功能:检测磁盘使用信息
格式:disk_usage(‘盘符’)
返回值:元组
归档和解包操作
归档:将多个文件合并到一个文件当中,这种操作方式就是归档。
解包:将归档的文件进行释放。
压缩:压缩时将多个文件进行有损或者无损的合并到一个文件当中。
解压缩:就是压缩的反向操作,将压缩文件中的多个文件,释放出来。
注意:压缩属于归档!
make_archive()
功能:归档函数,归档操作
格式:shutil.make_archive('目标文件路径','归档文件后缀','需要归档的目录')
返回值:归档文件的最终路径
unpack_archive()
功能:解包操作
格式:shutil.unpack_archive('归档文件路径','解包目标文件夹')
返回值:None
注意:文件夹不存在会新建文件夹
get_archive_formats()
功能:获取当前系统已注册的归档文件格式(后缀)
格式:shutil.get_archive_formats()
返回值:列表 [(后缀, 解释),(后缀, 解释),(后缀, 解释)...]
get_unpack_formats()
功能:获取当前系统已经注册的解包文件格式(后缀)
格式:shutil.get_unpack_formats()
返回值:列表 [(后缀,解释),(后缀,解释),(后缀,解释)...]
paramiko
paramiko 是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作,值得一说的是,fabric 和 ansible 内部的远程管理就是使用的 paramiko 来现实。
1、下载安装
1
2
3
pycrypto,由于 paramiko 模块内部依赖pycrypto,所以先下载安装pycrypto
pip3 install pycrypto
pip3 install paramiko
2、模块使用
#!/usr/bin/env python
#coding:utf-8
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.1.108', 22, 'alex', '123')
stdin, stdout, stderr = ssh.exec_command('df')
print stdout.read()
ssh.close();
import paramiko
private_key_path = '/home/auto/.ssh/id_rsa'
key = paramiko.RSAKey.from_private_key_file(private_key_path)
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('主机名 ', 端口, '用户名', key)
stdin, stdout, stderr = ssh.exec_command('df')
print stdout.read()
ssh.close()
import os,sys
import paramiko
t = paramiko.Transport(('182.92.219.86',22))
t.connect(username='wupeiqi',password='123')
sftp = paramiko.SFTPClient.from_transport(t)
sftp.put('/tmp/test.py','/tmp/test.py')
t.close()
import os,sys
import paramiko
t = paramiko.Transport(('182.92.219.86',22))
t.connect(username='wupeiqi',password='123')
sftp = paramiko.SFTPClient.from_transport(t)
sftp.get('/tmp/test.py','/tmp/test2.py')
t.close()
import paramiko
pravie_key_path = '/home/auto/.ssh/id_rsa'
key = paramiko.RSAKey.from_private_key_file(pravie_key_path)
t = paramiko.Transport(('182.92.219.86',22))
t.connect(username='wupeiqi',pkey=key)
sftp = paramiko.SFTPClient.from_transport(t)
sftp.put('/tmp/test3.py','/tmp/test3.py')
t.close()
import paramiko
pravie_key_path = '/home/auto/.ssh/id_rsa'
key = paramiko.RSAKey.from_private_key_file(pravie_key_path)
t = paramiko.Transport(('182.92.219.86',22))
t.connect(username='wupeiqi',pkey=key)
sftp = paramiko.SFTPClient.from_transport(t)
sftp.get('/tmp/test3.py','/tmp/test4.py')
t.close()
requests
Python 标准库中提供了:urllib 等模块以供 Http 请求,但是,它的 API 太渣了。它是为另一个时代、另一个互联网所创建的。它需要巨量的工作,甚至包括各种方法覆盖,来完成最简单的任务。
import urllib.request
f = urllib.request.urlopen('http://www.webxml.com.cn//webservices/qqOnlineWebService.asmx/qqCheckOnline?qqCode=424662508')
result = f.read().decode('utf-8')
import urllib.request
req = urllib.request.Request('http://www.example.com/')
req.add_header('Referer', 'http://www.python.org/')
r = urllib.request.urlopen(req)
result = f.read().decode('utf-8')
注:更多见 Python 官方文档:https://docs.python.org/3.5/library/urllib.request.html#module-urllib.request
Requests 是使用 Apache2 Licensed 许可证的 基于 Python 开发的 HTTP 库,其在 Python 内置模块的基础上进行了高度的封装,从而使得 Pythoner 进行网络请求时,变得美好了许多,使用 Requests 可以轻而易举的完成浏览器可有的任何操作。
1、安装模块
1
pip3 install requests
2、使用模块
# 1、无参数实例
import requests
ret = requests.get('https://github.com/timeline.json')
print(ret.url)
print(ret.text)
# 2、有参数实例
import requests
payload = {'key1': 'value1', 'key2': 'value2'}
ret = requests.get("http://httpbin.org/get", params=payload)
print(ret.url)
print(ret.text)
# 1、基本 POST 实例
import requests
payload = {'key1': 'value1', 'key2': 'value2'}
ret = requests.post("http://httpbin.org/post", data=payload)
print(ret.text)
# 2、发送请求头和数据实例
import requests
import json
url = 'https://api.github.com/some/endpoint'
payload = {'some': 'data'}
headers = {'content-type': 'application/json'}
ret = requests.post(url, data=json.dumps(payload), headers=headers)
print(ret.text)
print(ret.cookies)
requests.get(url, params=None, **kwargs)
requests.post(url, data=None, json=None, **kwargs)
requests.put(url, data=None, **kwargs)
requests.head(url, **kwargs)
requests.delete(url, **kwargs)
requests.patch(url, data=None, **kwargs)
requests.options(url, **kwargs)
# 以上方法均是在此方法的基础上构建
requests.request(method, url, **kwargs)
更多 requests 模块相关的文档见:http://cn.python-requests.org/zh_CN/latest/
3、Http 请求和 XML 实例
实例:检测 QQ 账号是否在线
import urllib
import requests
from xml.etree import ElementTree as ET
# 使用内置模块 urllib 发送 HTTP 请求,或者 XML 格式内容
"""
f = urllib.request.urlopen('http://www.webxml.com.cn//webservices/qqOnlineWebService.asmx/qqCheckOnline?qqCode=424662508')
result = f.read().decode('utf-8')
"""
# 使用第三方模块 requests 发送 HTTP 请求,或者 XML 格式内容
r = requests.get('http://www.webxml.com.cn//webservices/qqOnlineWebService.asmx/qqCheckOnline?qqCode=424662508')
result = r.text
# 解析 XML 格式内容
node = ET.XML(result)
# 获取内容
if node.text == "Y":
print("在线")
else:
print("离线")
实例:查看火车停靠信息
import urllib
import requests
from xml.etree import ElementTree as ET
# 使用内置模块 urllib 发送 HTTP 请求,或者 XML 格式内容
"""
f = urllib.request.urlopen('http://www.webxml.com.cn/WebServices/TrainTimeWebService.asmx/getDetailInfoByTrainCode?TrainCode=G666&UserID=')
result = f.read().decode('utf-8')
"""
# 使用第三方模块 requests 发送 HTTP 请求,或者 XML 格式内容
r = requests.get('http://www.webxml.com.cn/WebServices/TrainTimeWebService.asmx/getDetailInfoByTrainCode?TrainCode=G666&UserID=')
result = r.text
# 解析 XML 格式内容
root = ET.XML(result)
for node in root.iter('TrainDetailInfo'):
print(node.find('TrainStation').text,node.find('StartTime').text,node.tag,node.attrib)
注:更多接口猛击这里
paramiko 模块
import paramiko
# 创建 SSH 对象
ssh = paramiko.SSHClient()
# 允许连接不在 known_hosts 文件上的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname="192.168.0.99", port=22, username="root", password="rootroot")
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取结果
result = stdout.read().decode()
# 获取错误提示(stdout、stderr 只会输出其中一个)
err = stderr.read()
# 关闭连接
ssh.close()
print(stdin, result, err)
注:如果注释“ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())”这句,会报错。

类似问题可以为 linux 系统中 ~/.ssh/known_hosts 文件中的内容。
二、实现 SFTP 功能
import paramiko
# 连接虚拟机 centos 上的 ip 及端口
transport = paramiko.Transport(("192.168.0.99", 22))
transport.connect(username="root", password="rootroot")
# 将实例化的 Transport 作为参数传入 SFTPClient 中
sftp = paramiko.SFTPClient.from_transport(transport)
# 将“calculator.py”上传到 filelist 文件夹中
sftp.put('D:\python 库 \Python_shell\day05\calculator.py', '/filelist/calculator.py')
# 将 centos 中的 aaa.txt 文件下载到桌面
sftp.get('/filedir/aaa.txt', r'C:\Users\duany_000\Desktop\test_aaa.txt')transport.close()
注:如果遇到 Windows 中路径问题,链接如下网址 http://blog.csdn.net/elang6962/article/details/68068126
三、使用秘钥实现 SSH 功能
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('id_rsa31')
# 创建 SSH 对象
ssh = paramiko.SSHClient()ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='192.168.79.9', port=22, username='root', pkey=private_key)
stdin, stdout, stderr = ssh.exec_command('ifconfig')
res_out = stdout.read()
print(res_out.decode())
ssh.close()
四、使用秘钥实现 SFTP 功能
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('id_rsa31')
# 连接虚拟机 centos 上的 ip 及端口
transport = paramiko.Transport(("192.168.79.9", 22))
transport.connect(username="root", pkey=private_key)
# 将实例化的 Transport 作为参数传入 SFTPClient 中
sftp = paramiko.SFTPClient.from_transport(transport)
# 将“calculator.py”上传到 filelist 文件夹中
sftp.put('D:\python 库 \Python_shell\day05\calculator.py', '/filedir/calculator.py')
# 将 centos 中的 aaa.txt 文件下载到桌面
sftp.get('/filedir/oldtext.txt', r'C:\Users\duany_000\Desktop\oldtext.txt')transport.close()