1、模块
定义:模块,用一砣代码实现了某个功能的代码集合。 本质就是.py结尾的python文件(变量,函数,类,逻辑)
例:test.py 模块名:test
类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合。而对于一个复杂的功能来,可能需要多个函数才能完成(函数又可以在不同的.py文件中),n个 .py 文件组成的代码集合就称为模块。
如:os 是系统相关的模块;file是文件操作相关的模块
2、包(package)
python中新建一个package(包),和目录一模一样,区别在其下会自动生成一个 __init__.py 的文件
包:从逻辑上组织模块的,本质就是一个文件夹或者叫目录。必需带有一个 __init__.py 的文件(通过这个init文件调用其下的同级的.py 文件)
导入包的本质就是解释这个包下面的__init__.py文件
导入包的方法:
(1)同一级目录下:
import p1 (p1为包名) 直接执行p1下面的__init__.py文件
搜索路径:找的范围:sys.path这个里面定义的目录都是找的范围。(在执行文件之前先找。)
实例:
2.py文件的引用方法:
import day2p
(2)当不在同级目录下:将p1包的路径加载到sys.path这个变量中去:
import sys,os
print(sys)
知识点1:获取当前文件的绝对路径:
os.path.abspath(__file__) 获取当前文件的绝对路径
运行结果如下:
知识点2:获取当前文件的目录路径
os.path.dirname()
实例:
运行效果:
运行效果如下:
导入其他目录的下的包:格式:import 目录.包名
import day2.day2p
print(os.path.dirname(os.path.abspath(__file__)))---》 E:\PycharmProjects\pyday1\day5\module\
print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))---》 E:\PycharmProjects\pyday1\day5\
x=print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.append(x) 将这个位置加载到环境变量里边去
import p1 (此时就没问题了。因为p1包下面有个__init__.py的文件,并将该init的文件解释执行一遍,该包下其他的x.py文件不会执行!!!)
假如要导入p1包下面的其他的模块:
在p1包下面的init.py文件中添加:from . import x.py (这里的.代表了init.py这个文件的当前路径,加载其他的模块并运行,此时x.py文件里所有的代码都运行了),这样,加载了init.py文件后就运行了这initwenj文件里定义的其他文件
-------------------------------------------------------------------
3、导入优化:
实例:
同级目录下的jack.py和6.py文件
cat jack.py
print("代表2.py文件被import了。已经导入了")
def j():
print("This is jack.py file ,and L function.")
def k():
print("This is jack.py file ,and K function.")
def m():
print("This is jack.py file ,and M function.")
cat 6.py
1 import jack #这一步的运行结果是:“代表2.py文件被import了。已经导入了“ 2 def a(): 3 jack.j() 4 def b(): 5 jack.k() 6 a() # 这一步的运行结果是:This is jack.py file ,and L function. 7 b() # 这一步的运行结果是:This is jack.py file ,and K function.
优化方法:from MOKUAI-NAME import FANGFA-NAME
cat 6.py
1 from jack import j,k # jack 是另外一个模块的名,j、k是其里面的方法,*代表所有方法。 运行结果是:代表2.py文件被import了。已经导入了 2 def a(): 3 j() # 直接拿jack函数的j方法来使用, 运行结果是:This is jack.py file ,and L function 4 def b(): 5 k() # 直接拿jack函数的k方法来使用, 运行结果是:This is jack.py file ,and K function 6 a() 7 b()
4、模块导入(具体执行过程)
|-a.py
|-b.py
#cat a.py
1 name = "alex" 2 def sy(): 3 print("hello alex")
import 模块名 的具体实现过程
在b.py中调用a.py这个模块的功能
# cat b.py
1 import a # 这一步只是解释执行:将a模块执行后的结果赋值a这个变量,会运行里面的代码,该打印(print)的打印出来,该赋值的赋值。 2 print(a.name) # 调用a模块里面的name变量 3 a.sy() # 调用a模块并执行里面的sy方法
同时导入多个模块:
import module1,module2,module3
导入某个模块的所有方法:
from module1 import * ---------> 不建议使用,假如本地也有一个和这个模块里面同名的方法。有可能会造成程序出错,调用最近的同名方法。
#注意:此时将module1 模块里面的所有的代码都拿到当前了环境中加载了一遍,而没有导入module1 这个模块
#此时要适用module1 模块下的sy()方法:
sy() -------> 直接输入导入函数的其下的函数名就可以直接调用了
from module1 import sy ----------> 导入module1 模块的sy方法(注意不要写成了sy()!),作用:加载module1里面的sy函数的代码到当前,注意其作用是等于将sy函数的代码复制到当前,而不是立即执行了这个代码。是解释而不是执行。
a.py文件如下:
def b():
print("hello a function")
return 3
b.py文件如下:
from a import * -----------> 读到内存里面,执行了整 个a.py一遍,该print的打印出来,该定义变量的定义到变量里面。
print(b()) ----------> 这里才是执行,因为内存里已经有了,上面一句已经加载了.
实例:
#cat jack.py
1 print("代表2.py文件被import了。已经导入了") 2 def j(): 3 print("This is jack.py file ,and L function.") 4 def k(): 5 print("This is jack.py file ,and K function.") 6 def m(): 7 print("This is jack.py file ,and M function.") 8 return 4
#cat 6.py
from jack import *
print(m())
运行6.py的结果如下:
总结:import module 与 from module import xxx的区别:
前者在调用的时候需要加上模块名。即为:xxx.y (xxx为模块名,y为其下的方法。xxx是不带.py这部分的内容。)
后者在调用的时候,不需要写上模块名。直接运行其里面的方法。
5、标注库
5.1、时间模块:time与datetime
分为三种表示方式:
时间戳:time.time() 从1970年1月1号到现在的秒数
格式化的字符串:“2018-01-23 12:05:65”
格式化的元组: print(time.localtime())共9个元素,例如:
5.2、time.localtime 元组形式的时间
import time
print(time.localtime())
---->
#元组的形式:yday:一年当中的第几天,isdst:时区,0就代表不是夏令时。【UTC:格林尼治时间,DST:夏令时,中国:UTC+8,中国比标准时间要早8个小时】
time.struct_time(tm_year=2018, tm_mon=3, tm_mday=27, tm_hour=19, tm_min=36, tm_sec=29, tm_wday=1, tm_yday=86, tm_isdst=0)
注意:在localtime中的周是0-6的表现形式,0代表礼拜一,6代表礼拜天
5.3、print(time.timezone) 计算当前时间和标准时间差多少秒
----》
-28800 (28800/60/60=8 相差8个小时)
5.4、print(time.altzone)
--->
-32400 (UTC时间与夏令时的时差,很多国家实行夏令时)
获取时间戳:
5.5、print(time.time()) 时间戳,与1970年1月1日差多少秒
---》
1522152049.7275517
5.6、time.sleep(2) 程序睡2秒
5.7、将时间戳转换成元组的时间形式:
方法一:print(time.gmtime())
---->(不加参数的时候:传入的当前的时间,反馈出来的时间元组是标准时间:当前时间的UTC时间。 )
time.struct_time(tm_year=2018, tm_mon=3, tm_mday=27, tm_hour=12, tm_min=3, tm_sec=52, tm_wday=1, tm_yday=86, tm_isdst=0)
方法二:print(time.localtime())
---->
time.struct_time(tm_year=2018, tm_mon=3, tm_mday=27, tm_hour=20, tm_min=11, tm_sec=18, tm_wday=1, tm_yday=86, tm_isdst=0)
5.8、时间戳转成结构化的元组的形式(通过元组,就可以读取元组里面的值)
localtime()的用法1:读取当前时间的年份或者月份
1 import time 2 x =time.localtime() 3 print(x) 4 print(x.tm_year)
------>
time.struct_time(tm_year=2018, tm_mon=4, tm_mday=17, tm_hour=9, tm_min=45, tm_sec=3, tm_wday=1, tm_yday=107, tm_isdst=0)
2018
localtime()的用法2:传入时间戳(或者具体的秒数),然后根据时间戳计算出所需要的年份或者月份等。
可以传入时间戳
也可以传入任意的秒数
import time x =time.localtime(6411131311) print(x) print(x.tm_year)
print("This is %d year and the %d day."%(x.tm_year,x.tm_yday))
------------>
time.struct_time(tm_year=2173, tm_mon=2, tm_mday=28, tm_hour=5, tm_min=48, tm_sec=31, tm_wday=6, tm_yday=59, tm_isdst=0)
2173
This is 2173 year and the 59 day.
5.9、元组转换成时间戳:mktime()
1 import time 2 x =time.localtime() 3 print(time.mktime(x)) 4 5 y = time.localtime(2347983248) 6 print(time.mktime(y))
-------------------------------
1523931627.0
2347983248.0
5.10、元组转换成格式化的字符串:strftime()
import time x = time.localtime(3423432423)
print(x) print(time.strftime("%Y-%m-%d %H:%M:%S",x))
--------------------------------------------
time.struct_time(tm_year=2078, tm_mon=6, tm_mday=26, tm_hour=9, tm_min=27, tm_sec=3, tm_wday=6, tm_yday=177, tm_isdst=0)
2078-06-26 09:27:03 ---->结果是:格式化的字符串,安装指定的格式的变量调取x中的值。
5.11、格式化的字符串转换成元组
import time x = time.strptime("2016-08-20 15:23:45","%Y-%m-%d %H:%M:%S") print(x)
-------------------------------------
time.struct_time(tm_year=2016, tm_mon=8, tm_mday=20, tm_hour=15, tm_min=23, tm_sec=45, tm_wday=5, tm_yday=233, tm_isdst=-1)
总结:
strftime("格式",time.localtime()) ----> 结果是 格式化的字符串
strptime("格式化的字符串",“格式”) ---> 结果是 元组(struct_time)
5.12、将元组转成成字符串:asctime() (出入空值就是当前时间)
import time x = time.asctime() print(x,type(x))
----------------------
Tue Apr 17 10:34:12 2018
5.13、将时间戳转换成字符串:ctime(), 空就是传入当前的,和time.asctime 俩接收的参数不一样,但结果都是一样。
import time print(time.ctime()) print(time.ctime(23434234.234234))
------------------------------------
Tue Apr 17 10:42:35 2018
Tue Sep 29 13:30:34 1970
--------------------------------------------------------------------------------------------------
5.14、datetime()
实例:
import datetime
print(datetime.datetime.now())
print(datetime.datetime.now()+datetime.timedelta(3))#当前时间+3天
print(datetime.datetime.now()+datetime.timedelta(-3))#当前时间-3天
print(datetime.datetime.now()+datetime.timedelta(hours=3))#当前时间+3小时
print(datetime.datetime.now()+datetime.timedelta(minutes=30))#当前时间+30分
修改当前时间
c_time = datetime.datetime.now()
print(c_time.replace(minute=3,hour=2))#时间替换
6、random 模块
6.1 生成一个0到1之间的随机数
import random
print(random.random()) #0.6445010863311293随机一个整数:
6.2 生成一个整数(必需要带两个指定范围的参数a,b)
print(random.randint(1,7)) ------> 1到7之间,可以取到1和7这个两个值!!!
print(random.randint(-1000,10)) ---------> 可以是负数
#random.randint()的函数原型为:random.randint(a,b),用于生成一个指定范围内的整数。
6.3 一个循环的取值区间作为范围
print(random.randrange(1,10)) ---> 5 从1开始,到range(10)结束,最大为9,即范围为1到9.
print(random.randrange(10,100,2)) ---> 从指定范围内,按指定基数递增的集合中获取一个随机数。
#结果相当于从[10,12,14,16,...96,98]序列中获取一个随机数。
#random.randrange(10,100,2)在结果上与random.choice(range(10,100,2)等效。
6.4 random.choice的用法:从序列中获取一个随机元素,可以是列表,字符串,元组等,从中取值
print(random.choice('liukuni')) #i 放入的是一个序列,可以是字符串,列表,元组。都是从中取值。
#其函数原型为:random.choice(sequence)。参数sequence表示一个有序类型。
#这里要说明一下:sequence在python不是一种特定的类型,而是泛指一系列的类型。
#list,tuple,字符串都属于sequence。有关sequence可以查看python手册数据模型这一章。
#下面是使用choice的一些例子:
print(random.choice("学习Python")) # 学
print(random.choice(["JGood","is","a","handsome","boy"])) # List
print(random.choice(("Tuple","List","Dict"))) # List
6.5 random.sample的用法:从指定序列中随机获取指定长度的片断
print(random.sample([1,2,3,4,5],3)) #[1,2,5] ,3代表长度,就是取3个。
#random.sample的函数原型为:random.sample(sequence,k),从指定序列中随机获取指定长度的片断。sample函数不会修改原有序列。
实际应用:
#!/usr/bin/envpython
#encoding:utf-8
import random
import string
#随机整数:
print(random.randint(0,99))#70
#随机选取0到100间的偶数:
print(random.randrange(0,101,2))#4
#随机浮点数:
print(random.random())#0.2746445568079129 ---》 默认的0到1之间的浮点数
print(random.uniform(1,10))#9.887001463194844 ----》指定区间的浮点数。
#随机字符:
print(random.choice('abcdefg%^*f'))#f
#多个字符中选取特定数量的字符:
print(random.sample('abcdefghij',3))#['f','h','d']
#随机选取字符串:
print(random.choice(['apple','pear','peach','orange','lemon']))#apple
#洗牌# 打乱顺序的作用
items=[1,2,3,4,5,6,7]
print(items)#[1,2,3,4,5,6,7]
random.shuffle(items)
print(items)#[1,4,7,2,5,3,6]
生成随机验证码:
1 import random 2 checkcode='' 3 for i in range(4): 4 current=random.randrange(0,4) 5 if current!=i: 6 temp=chr(random.randint(65,90)) 7 else: 8 temp=random.randint(0,9) 9 checkcode+=str(temp) 10 print(checkcode)
7、os模块 (Python中演示):
os模块提供对操作系统进行调用的接口
os模块(在pycharm中演示)
模拟对操作系统的操作,提供对操作系统进行调用的接口
7.1 os.getcwd() :获取当前工作目录,即当前python脚本工作的目录路径 类似于Linux:pwd
import os
print(os.getcwd())
------------------------------------
I:\pathon合集\python工作目录\day1
7.2 os.chdir("dirname")改变当前脚本工作目录;相当于shell下cd
>>>os.chdir("C:\\User") (注意前面一个反斜杠表示转义后面的\ 的意思)或者 :os.chdir(r"C:\User") 效果一样的
import os print(os.getcwd()) os.chdir("I:\\pathon合集") print(os.getcwd()) ------------------------------------ I:\pathon合集\python工作目录\day1 I:\pathon合集
7.3 os.curdir 返回当前目录:('.')
os.pardir获取当前目录的父目录字符串名:('..')
7.4 创建目录
当前路径创建目录
os.mkdir('dirname')生成单级目录;相当于shell中mkdirdirname,不能递归的创建文件
递归创建目录
os.makedirs('dirname1/dirname2') 可生成多层递归目录,当前路径下创建递归目录。
os.makedirs(r"C:\a\b\c\d") 实现在windows系统中操作文件,在指定的绝对路径下创建递归目录
7.5 清理空文件夹
删除当前路径下的空目录:
os.rmdir('dirname')删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdirdirname
递归删除多级空目录:
os.removedirs('dirname1')若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
import os os.chdir("I:\pathon合集") print(os.getcwd()) os.removedirs("I:\\pathon合集\AAA\BBB\CCC") print(os.getcwd()) --------------------------------------------------- I:\pathon合集 I:\pathon合集 ---------> 此时在上文创建的 AAA\BBB\CCC 等多级目录已经全部删除了
7.6 os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
import os print(os.listdir("I:\\pathon合集")) ------------------------------------------------- ['01.8.python就业培训视频教程web版', 'pathon安装包', 'python书籍', 'python工作目录', 'python练习目录', '老男孩教育_全栈Python视频1_Alex老师python']
7.6 os.remove()删除一个文件
import os print(os.listdir("I:\\pathon合集")) os.remove("I:\\pathon合集\\aa") #注意这里的文件路径 \\aa ,将第一个a要转义,否则出错!!!! print(os.listdir("I:\\pathon合集")) -------------------------------------------------------- ['01.8.python就业培训视频教程web版', 'aa', 'pathon安装包', 'python书籍', 'python工作目录', 'python练习目录', '老男孩教育_全栈Python视频1_Alex老师python'] ['01.8.python就业培训视频教程web版', 'pathon安装包', 'python书籍', 'python工作目录', 'python练习目录', '老男孩教育_全栈Python视频1_Alex老师python']
7.7 重命名一个文件
os.rename("oldname","newname")重命名文件/目录
import os print(os.listdir("I:\\pathon合集")) os.rename("I:\\pathon合集\\bb.txt","I:\\pathon合集\\bbbb.txt") # 注意:文件路径分隔符采用“\\”
print(os.listdir("I:\\pathon合集"))
--------------------------------------------------------------
['01.8.python就业培训视频教程web版', 'bb.txt', 'pathon安装包', 'python书籍', 'python工作目录', 'python练习目录', '老男孩教育_全栈Python视频1_Alex老师python'] ['01.8.python就业培训视频教程web版', 'bbbb.txt', 'pathon安装包', 'python书籍', 'python工作目录', 'python练习目录', '老男孩教育_全栈Python视频1_Alex老师python']
7.8 os.stat('path/filename')获取文件/目录信息
import os print(os.stat("I:\\pathon合集\\bbbb.txt")) # 注意:文件路径分隔符采用“\\” ---------------------------------------------------------- os.stat_result(st_mode=33206, st_ino=28710447624526907, st_dev=385319, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1523949100, st_mtime=1523949100, st_ctime=1523949100)
7.9 其他各种系统操作
os.sep输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep输出用于分割文件路径的字符串
os.name输出字符串指示当前使用平台。 win->'nt';Linux->'posix'
import os print(os.name) ----------------- nt
7.10 os.system("bashcommand")运行shell命令,在windows中相当于cmd中,在Linux中相当于shell中:
import os print(os.name) os.system("dir") ------------------------- nt ������ I �еľ��� ��� ������к��� 0005-E127 I:\pathon�ϼ�\python����Ŀ¼\day1 ��Ŀ¼ 2018/04/17 �ܶ� ���� 03:38. 2018/04/17 �ܶ� ���� 03:38 .. 2018/04/16 ��һ ���� 03:47 234 2.py 2018/04/17 �ܶ� ���� 03:38 64 6.py 2018/04/17 �ܶ� ���� 02:40 AAA 2018/04/17 �ܶ� ���� 09:23 261 jack.py 2018/04/16 ��һ ���� 03:20 p1 2018/04/17 �ܶ� ���� 09:23 __pycache__ 3 ���ļ� 559 �ֽ� 5 ��Ŀ¼ 204,265,115,648 �����ֽ�
os.environ获取系统环境变量
os.path.abspath(path)返回path规范化的绝对路径
os.path.split(path)将path分割成目录和文件名二元组返回
os.path.dirname(path)返回path的目录。其实就是os.path.split(path)的第一个元素
os.path.basename(path)返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.exists(path)如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path)如果path是绝对路径,返回True
os.path.isfile(path)如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path)如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[,path2[,...]])将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path)返回path所指向的文件或者目录的最后存取时间
os.path.getmtime(path)返回path所指向的文件或者目录的最后修改时间
只取目录:
os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素,这个目录可以不存在,不效验真假
os.path.dirname(r"C:\A\B\C\D\x.stxt")
只取文件名,结尾的值:
os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
8、sys模块:
8.1 sys.argv 命令行参数List,第一个元素是程序本身路径,带着一个脚本,在传入参数来掩饰
[root@localhost tmp]# vim p.py
[root@localhost tmp]# cat p.py
import sys
print(sys.argv)
[root@localhost tmp]# python p.py 1 2 3 4 5
['p.py', '1', '2', '3', '4', '5']
8.2 sys.exit(n) 退出程序,正常退出时exit(0)
利用sys.exit() 可以一次退成多层循环,退出整个程序
import sys while True: print("1111111111111111111111111111") while True: print("2222222222222222222222222222222222") while True: print("44444444444444444444444444444444444444") sys.exit() print("out of the loop")
---------------------------------------------------------------------------------
C:\Users\Administrator\AppData\Local\Programs\Python\Python36\python.exe I:/pathon合集/python工作目录/day1/6.py 1111111111111111111111111111 2222222222222222222222222222222222 44444444444444444444444444444444444444 进程已结束,退出代码0
8.3 其他几种sys模块用法
sys.version 获取Python解释程序的版本信息
sys.maxsize 最大的Int值
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform 返回操作系统平台名称
import sys print(sys.version) print(sys.maxsize) print(sys.path) print(sys.platform) --------------------------------- 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] 9223372036854775807 ['I:\\pathon合集\\python工作目录\\day1', 'I:\\pathon合集\\python工作目录', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\python36.zip', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\DLLs', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages'] win32
sys.stdout.write('please:') ----> 'please:'
val = sys.stdin.readline()[:-1]
9,shutil模块 :拷贝文件
http://www.cnblogs.com/wupeiqi/articles/4963027.html
shutil.copy(src, dst)
拷贝文件和权限
高级的 文件、文件夹、压缩包 处理模块
shutil.copyfileobj(fsrc, fdst[, length])
将文件内容拷贝到另一个文件中,可以部分内容
例1,标准版复制文件shutil.copyfileobj():
import shutil
f1 = open("aa",encoding="utf-8") 注意:benjiebiji这个文件是在当前路径下存在的。f1是打开后的内存对象
f2 = open("aa.bak","w",encoding="utf-8") 注意:biji2这个文件是不存在的。会创建这个f2这个内存对象。
shutil.copyfileobj(f1,f2)
---> 运行后会生成biji2,内容和源文件一样
例2,高效版复制文件shutil.copyfile():
import shutil
shutil.copyfile("笔记1",“笔记x”) ---------> 笔记1是存在的,笔记x是要生成的文件
例3,拷贝权限:shutil.copymode(src, dst)
仅拷贝权限。内容、组、用户均不变(在Windows上不明显,Linux上试验下,有可能是755这个权限一样,但所有者和组均为新用户的)
例4,拷贝状态的信息 shutil.copystat(src, dst)
Linux里面去演示,Windows上不明显,要求两个文件都存在。
,包括:mode bits, atime, mtime, flags
例5,同时拷贝文件和权限 shutil.copy(f1,f2)
import shutil,os print(os.getcwd()) shutil.copy('aa','bb') -----------> aa文件时存在的。bb文件时通过shutil.copy 生成的。要求两者是在当前路径下的。 ------------------------------- I:\pathon合集\python工作目录\day1
例6,拷贝文件和状态信息 shutil.copy2(src, dst) ----> 用得不多
例7,递归的拷贝文件:等于是连目录一起拷贝
shutil.copytree(src, dst, symlinks=False, ignore=None)
递归的去拷贝文件
例如:copytree(source, destination, ignore=ignore_patterns('*.pyc', 'tmp*'))
应用实例:
shutil.copytree("test4","new_test4")
这里的test4是一个目录,并且其下有多层目录和文件,new_test4是不存在的。执行后会生成。
例8:递归的去删除文件,shutil.rmtree(path[, ignore_errors[, onerror]])
实例:
shutil.rmtree("new_test4")
比调用os.rmdir要好用些
例9:递归的去移动文件,shutil.move(src, dst)
例10:文件打包和压缩:shutil.make_archive(base_name, format,...)
创建压缩包并返回文件路径,例如:zip、tar
base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,如:www =>保存至当前路径
如:/Users/wupeiqi/www =>保存至/Users/wupeiqi/
format: 压缩包类型,“zip”, “tar”, “bztar”,“gztar”
root_dir: 要压缩的文件夹路径(默认当前目录)
owner: 用户,默认当前用户
group: 组,默认当前组
logger:用于记录日志,通常是logging.Logger对象 ,这一条先不用管,以后学
实例:
import shutil
shutil.make_archive("shutil_archive_test","zip","E:\PycharmProjects\pyday1\day5")
要生成的当前路径的压缩文件名 压缩类型 压缩的原文件(文件夹)
注意:这个day5这个文件最好不要是自己的目录。否则会生成多层的压缩包。压缩自己的里面又有压缩自己,有可能会进入 到死循环
用途:通过Python就可以压缩。而不用在调用shell命令来压缩文件了。直接用shutil就可以实现了
#将 /Users/wupeiqi/Downloads/test 下的文件打包放置当前程序目录
import shutil
ret = shutil.make_archive("wwwwwwwwww", 'gztar', root_dir='/Users/wupeiqi/Downloads/test')
#将 /Users/wupeiqi/Downloads/test 下的文件打包放置 /Users/wupeiqi/目录
import shutil
ret = shutil.make_archive("/Users/wupeiqi/wwwwwwwwww", 'gztar', root_dir='/Users/wupeiqi/Downloads/test')
=============================================================================
shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,详细:
import zipfile
# 单独的一个一个压缩文件用这个
z = zipfile.ZipFile('laxi.zip', 'w') ------------》 laxi.zip就是压缩后的名称,w写的模式。默认是r,也即是解压缩的模式
z.write('a.log') ---------------------------> 传入要压缩的对象,
z.write('data.data')
z.close()
单独的一个一个压文件实例:
import zipfile
z = zipfile.ZipFile("day5.zip","w")
z.write(‘1.py’)
print('----------------------------')
z.write('2.py')
z()
--->运行
生成day5.zip这个文件,打开后里面有1.py和2.py两个文件
# 解压
z = zipfile.ZipFile('laxi.zip', 'r')
z.extractall() ---------------------------》全解压
z.close()
import tarfile
# 压缩
tar = tarfile.open('your.tar','w')
tar.add('/Users/wupeiqi/PycharmProjects/bbs2.zip', arcname='bbs2.zip')
tar.add('/Users/wupeiqi/PycharmProjects/cmdb.zip', arcname='cmdb.zip')
tar.close()
# 解压
tar = tarfile.open('your.tar','r')
tar.extractall() # 可设置解压地址
tar.close()
import zipfile # 压缩 z = zipfile.ZipFile('laxi.zip', 'w') z.write('a.log') z.write('data.data') z.close() # 解压 z = zipfile.ZipFile('laxi.zip', 'r') z.extractall() z.close() import tarfile # 压缩 tar = tarfile.open('your.tar','w') tar.add('/Users/wupeiqi/PycharmProjects/bbs2.log', arcname='bbs2.log') tar.add('/Users/wupeiqi/PycharmProjects/cmdb.log', arcname='cmdb.log') tar.close() # 解压 tar = tarfile.open('your.tar','r') tar.extractall() # 可设置解压地址 tar.close()
10 json 和 pickle
用于序列化的两个模块(两者之间的用法完全一样)
json,用于字符串 和 python数据类型间进行转换(解决了不同的语言php,Java和平台之间的数据交换,仅支持通用的数据类型,不是所有的数据类型)
pickle,用于python特有的类型 和 python的数据类型间进行转换
Json模块提供了四个功能:dumps、dump、loads、load
pickle模块提供了四个功能:dumps、dump、loads、load(Python语言自己的数据交换,类,函数等。优势在于支持所有的Python的数据 类型)
Python3.x里可以dump多次,只能load一次。
import pickle
data = {'k1':123,'k2':'hello'}
#pickle.dumps 将数据通过特殊的形式转换为只有Python语言认识的字符串
p= pickle.dumps(data)
print(p)
#pickle.dump 将数据通过特殊的形式转换为只有Python语言认识的字符串,并写入文件
with open('D:\a','w') as fp:
pickle.dump(data,fp)
import json
# json.dumps 将数据通过的特殊的形式转换为所有程序语言都认识的字符串
j = json.dumps.dumps(data)
print(j)
#json.dump 数据通过特殊的形式转换为所有的程序语言都认识的字符串,并写入文件
with open('D:\a','w') as fp:
json.dump(data,fp)
=======================================================================================================
11、shelve 模块
shelve类似于一个存储持久化对象的持久化字典,即字典文件。使用方法也类似于字典。
(1)、shelve模块是一个简单的key,value将内存数据通过文件持久化的模块。
(2)、shelve模块可以持久化任何pickle可支持的python数据格式。
(3)、shelve就是pickle模块的一个封装。
(4)、shelve模块是可以多次dump和load。
11.1、数据持久化
import shelve,datetime
i = {'name':'wang','age':22} name = ['jack1','jack2','jack3'] t = datetime.datetime.now() with shelve.open('mm') as f: f['name'] = name #持久化列表 f['i'] = i #持久化字典 f['t'] = t # 持久化时间类型
执行代码后会生成3个文件:shelve.txt.bak、shelve.txt.dat、shelve.txt.dir。
shelve.txt.bak 的内容
'i', (512, 45)
'name', (0, 42)
't', (1024, 44)
shelve.txt.dat
一堆乱码
shelve.txt.dir 的内容
'i', (512, 45)
'name', (0, 42)
't', (1024, 44)
11.2、数据读取,我们使用get来获取数据
import shelve with shelve.open('mm') as f: n = f.get('name') i2 = f.get('i') t2 = f.get('t') print(n) print(i2) print(t2) --------------------------------------
['jack1', 'jack2', 'jack3'] {'name': 'wang', 'age': 22} 2018-04-17 17:27:45.058138
12 、xml处理模块 (以后用的不多,但得知道是怎么回事)
xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,在json还没诞生的黑暗年代,大家只能选择用xml呀,至今很多传统公司如金融行业的很多系统的接口还主要是xml。
xml的格式如下,就是通过<>节点来区别数据结构的:
复制下面的代码放到pycharm里面,python.file ,取名:xmltest.xml
xml协议在各个语言里的都 是支持的,在python中可以用以下模块操作xml
import xml.etree.ElementTree as ET
tree = ET.parse("xmltest.xml") ---------- 要处理的文件名:xmltest.xml 两个文件在同级目录下
root = tree.getroot() ======== 是一个内存对象。
print(root.tag) --------- data
#遍历xml文档
for child in root:
print(child.tag, child.attrib)
for i in child:
print(i.tag,i.text)
#只遍历year 节点
for node in root.iter('year'):
print(node.tag,node.text)
修改和删除xml文档内容
import xml.etree.ElementTree as ET
tree = ET.parse("xmltest.xml")
root = tree.getroot()
#修改
for node in root.iter('year'):
new_year = int(node.text) + 1
node.text = str(new_year)
node.set("updated","yes")
tree.write("xmltest.xml")
#删除node
for country in root.findall('country'):
rank = int(country.find('rank').text)
if rank > 50:
root.remove(country)
tree.write('output.xml')
自己创建xml文档
import xml.etree.ElementTree as ET
new_xml = ET.Element("namelist") (根节点)
name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"}) (子节点 节点名,属性)
age = ET.SubElement(name,"age",attrib={"checked":"no"}) (上面的name的子节点)
sex = ET.SubElement(name,"sex")
age.text = '33'
name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"})
age = ET.SubElement(name2,"age")
age.text = '19'
et = ET.ElementTree(new_xml) #生成文档对象
et.write("test.xml", encoding="utf-8",xml_declaration=True) # 写入test.xml文件
ET.dump(new_xml) #打印生成的格式
13、 PyYaml
python中yaml的模块的使用,解析slatstack的配置文件中的pool和后端的redis主机。采用shell解析yml文件太麻烦,正好python有正对于yaml文件解析的pyyaml模块
使用pyyaml模块最多的就是load()和dump()两个函数
(1)安装yaml模块到机器环境中
(2)编写yaml配置文件test.yaml
name: Tom Smith age: 37 spouse: name: Jane Smith age: 25 children: - name: Jimmy Smith age: 15 - name1: Jenny Smith age1: 12
(3)编写解析yaml文件的python程序test.py
import sys sys.path.insert(0, '/home/wahaha/coding/python') import yaml f = open('test.yaml') x = yaml.load(f) print type(x) print x
程序输出的结果为(yaml.load产出的是dict哦):
'dict'> {'age': 37, 'spouse': {'age': 25, 'name': 'Jane Smith'}, 'name': 'Tom Smith', 'children': [{'age': 15, 'name': 'Jimmy Smith'}, {'age1': 12, 'name1': 'Jenny Smith'}]}
YAML 是专门用来写配置文件的语言,非常简洁和强大,远比 JSON 格式方便。
YAML在python语言中有PyYAML安装包,下载地址:https://pypi.python.org/pypi/PyYAML
1、简介
YAML 语言(发音 /ˈjæməl/ )的设计目标,就是方便人类读写。它实质上是一种通用的数据串行化格式。
它的基本语法规则如下:
1、大小写敏感
2、使用缩进表示层级关系
3、缩进时不允许使用Tab键,只允许使用空格。
4、缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
5、#
表示注释,从这个字符一直到行尾,都会被解析器忽略,这个和python的注释一样
YAML 支持的数据结构有三种:
1、对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
2、数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
3、纯量(scalars):单个的、不可再分的值。字符串、布尔值、整数、浮点数、Null、时间、日期
二、字符串
#######################################字符串############################################## #1、字符串默认不使用引号表示 str1: 这是一个字符串 #2、如果字符串之中包含空格或特殊字符,需要放在引号之中。 str2: '内容: *字符串' #3、单引号和双引号都可以使用,双引号不会对特殊字符转义。 str3: '内容\n字符串' str4: "content\n string" #4、单引号之中如果还有单引号,必须连续使用两个单引号转义。 s3: 'labor''s day' #5、字符串可以写成多行,从第二行开始,必须有一个单空格缩进。换行符会被转为空格 strline: 这是一段 多行 字符串 #6、多行字符串可以使用|保留换行符,也可以使用>折叠换行 this: | Foo Bar that: > Foo Bar #7、+表示保留文字块末尾的换行,-表示删除字符串末尾的换行。 s4: | Foo4 s5: |+ Foo5 s6: |- Foo6 s7: | Foo7
三、对象
###################################对象#################### #1、对象的一组键值对,使用冒号结构表示。 animal: pets #{'animal': 'pets'} # ##2、Yaml 也允许另一种写法,将所有键值对写成一个行内对象 dict1: { name: Steve, foo: bar } #{'dict1': {'foo': 'bar', 'name': 'Steve'}}
四、数组
####################################数组################### # 1、数组可以采用行内表示法。 animal: [Cat, Dog] #{'animal': ['Cat', 'Dog']} #2、一组连词线开头的行,构成一个数组。 animal1: - Cat - Dog - Goldfish # {'animal1': ['Cat', 'Dog', 'Goldfish']}
五、复合结构
############################复合结构########################## #对象和数组可以结合使用,形成复合结构 languages: - Ruby - Perl - Python websites: YAML: yaml.org Ruby: ruby-lang.org Python: python.org Perl: use.perl.org #{'languages': ['Ruby', 'Perl', 'Python'], 'websites': {'Python': 'python.org', 'YAML': 'yaml.org', 'Ruby': 'ruby-lang.org', 'Perl': 'use.perl.org'}} db: host: xxx port: 3306 user: weibospider password: xxx db_name: weibo db_type: mysql #{'db': {'host': 'xxx', 'db_name': 'weibo', 'user': 'weibospider', 'db_type': 'mysql', 'password': 'xxx', 'port': 3306}}
六、纯量
##########################纯量############################# #1、数值直接以字面量的形式表示 number: 12.30 #{'number': 12.3} #2、布尔值用true和false表示 isSet: true #{'isSet': True} isSet1: false #{'isSet1': False} 3、null用~表示 parent: ~ #{'parent': None} #4、时间采用 ISO8601 格式。 time1: 2001-12-14t21:59:43.10-05:00 #{'time1': datetime.datetime(2001, 12, 15, 2, 59, 43, 100000)} ##5、日期采用复合 iso8601 格式的年、月、日表示。 date: 2017-07-31 #{'date': datetime.date(2017, 7, 31)} #6、YAML 允许使用两个感叹号,强制转换数据类型。 int_to_str: !!str 123 #{'bool_to_str': 'true'} bool_to_str: !!str true #{'bool_to_str': 'true'}
用来写配置文档的。会比较简单些
PyYAML文档 http://pyyaml.org/wiki/PyYAMLDocumentation
PyYAML现在维持在https://github.com/yaml/pyyaml。这个页面是留给历史的目的。
标准的yaml语法举例:saltstack
file_roots:
base:
- /srv/salt/
dev:
- /srv/salt/dev/services
- /srv/salt/dev/states
prod:
- /srv/salt/prod/services
- /srv/salt/prod/states
#这个/tmp/foo.conf其实是一个ID,但它直接默许你要管理的minion机器上的文件位置
/tmp/foo.conf:
#使用state中的file.managed模块来管理,具体配置参考可以通过salt 'minion' sys.state_doc file.managed这条命令来查阅
file.managed:
#定认本端master的源文件key
- source:
#这里的key中的VALUE对应的是salt://foo.conf,指的是salt中base目录(/srv/salt/) 下的foo.conf
- salt://foo.conf
#将目标minion的文件控制其文件权限
- user: root
- user: root
- mode: 644
#备份minion的源文件
- backup: minion
安装
PyYAML-3.12.tar下载源代码包,解压并打开它,去pyyaml - 3.12的目录并运行
$ python setup.py install
如果你想使用LibYAML绑定,速度远远超过纯Python版本,您需要下载并安装LibYAML。然后你可以构建和安装绑定通过执行
$ python setup.py --with-libyaml install
为了使用LibYAML基于解析器和发射器,使用类 CParser和 CEmitter。例如,
from yaml import load, dump
try:
from yaml import CLoader as Loader, CDumper as Dumper
exceptImportError:
from yaml import Loader, Dumper
# ...
data = load(stream, Loader=Loader) #导入 一堆东西。load一下就可以了,load后会变成字典的格式
# ...
output = dump(data, Dumper=Dumper) #写入一堆东西。只要dump一下就可以了
注意,有一些微妙的(但不是很重要)纯Python和之间的区别LibYAML基于解析器和发射器。
常见问题
字典没有嵌套的集合是不正确了
为什么
import yaml
document =""" a: 1 b: c: 3 d: 4"""print yaml.dump(yaml.load(document))
给
a: 1
b: {c: 3, d: 4}
(见# 18日# 24)?
这是一个正确的输出尽管嵌套映射的风格是不同的。
默认情况下,PyYAML选择集合的风格取决于是否有嵌套的集合。如果一个集合了嵌套的集合,它将分配块的风格。否则它会流风格。
如果你总是想要收藏序列化块风格,设置参数 default_flow_style的 dump()来 False。例如,
>>>print yaml.dump(yaml.load(document), default_flow_style=False)
a: 1
b:
c: 3
d: 4
Python 3支持
从3.08版开始,PyYAML和LibYAML绑定提供一个完整的支持Python 3。这是一个短的轮廓的差异PyYAML Python 2和Python 3版本之间的API。
在Python中2:
str对象转换为 !!str, !!python/str或 !binary取决于节点的对象是一个ASCII,utf - 8或二进制字符串。
unicode对象转换为 !!python/unicode或 !!str根据节点是否对象是一个ASCII字符串。
yaml.dump(data)生成的文档作为一个utf - 8编码 str对象。
yaml.dump(data, encoding=('utf-8'|'utf-16-be'|'utf-16-le'))产生一个 str对象指定的编码。
yaml.dump(data, encoding=None)产生一个 unicode对象。
在Python 3:
str对象转换为 !!str节点。
bytes对象转换为 !!binary节点。
从兼容性角度看, !!python/str和 !python/unicode标签仍然支持并转换为相应的节点 str对象。
yaml.dump(data)作为一个生产文档 str对象。
yaml.dump(data, encoding=('utf-8'|'utf-16-be'|'utf-16-le'))产生一个 bytes对象指定的编码。
教程
开始导入 yaml包中。
>>>import yaml
加载YAML
警告:它是不安全的 yaml.load来自不受信任来源的任何数据! yaml.load一样强大 pickle.load所以可以叫任何Python函数。检查 yaml.safe_load尽管函数。
这个函数 yaml.load将一个YAML文件转换为Python对象。
>>> yaml.load("""... - Hesperiidae... - Papilionidae... - Apatelodidae... - Epiplemidae... """)
['Hesperiidae', 'Papilionidae', 'Apatelodidae', 'Epiplemidae']
yaml.load接收一个字节的字符串,Unicode字符串,一个开放的二进制文件对象,或开放的文本文件对象。一个字节字符串或文件必须使用utf - 8编码,utf-16-be或utf-16-le编码。 yaml.load检测编码通过检查BOM(字节顺序标记)序列在字符串的开始/文件。如果没有BOM,utf - 8编码。
yaml.load返回一个Python对象。
>>> yaml.load(u"""... hello: Привет!... """) # In Python 3, do not use the 'u' prefix
{'hello': u'\u041f\u0440\u0438\u0432\u0435\u0442!'}
>>> stream =file('document.yaml', 'r') # 'document.yaml' contains a single YAML document.>>> yaml.load(stream)
[...] # A Python object corresponding to the document.
如果一个字符串或一个文件包含一些文件,你可以加载的 yaml.load_all函数。
>>> documents ="""... ---... name: The Set of Gauntlets 'Pauraegen'... description: >... A set of handgear with sparks that crackle... across its knuckleguards.... ---... name: The Set of Gauntlets 'Paurnen'... description: >... A set of gauntlets that gives off a foul,... acrid odour yet remains untarnished.... ---... name: The Set of Gauntlets 'Paurnimmen'... description: >... A set of handgear, freezing with unnatural cold.... """>>>for data in yaml.load_all(documents):
... print data
{'description': 'A set of handgear with sparks that crackle across its knuckleguards.\n',
'name': "The Set of Gauntlets 'Pauraegen'"}
{'description': 'A set of gauntlets that gives off a foul, acrid odour yet remains untarnished.\n',
'name': "The Set of Gauntlets 'Paurnen'"}
{'description': 'A set of handgear, freezing with unnatural cold.\n',
'name': "The Set of Gauntlets 'Paurnimmen'"}
PyYAML允许您构建一个Python任何类型的对象。
>>> yaml.load("""... none: [~, null]... bool: [true, false, on, off]... int: 42... float: 3.14159... list: [LITE, RES_ACID, SUS_DEXT]... dict: {hp: 13, sp: 5}... """)
{'none': [None, None], 'int': 42, 'float': 3.1415899999999999,
'list': ['LITE', 'RES_ACID', 'SUS_DEXT'], 'dict': {'hp': 13, 'sp': 5},
'bool': [True, False, True, False]}
甚至可以构建使用Python类的实例 !!python/object标签。
>>>class Hero:
... def__init__(self, name, hp, sp):
... self.name = name
... self.hp = hp
... self.sp = sp
... def__repr__(self):
... return"%s(name=%r, hp=%r, sp=%r)"% (
... self.__class__.__name__, self.name, self.hp, self.sp)
>>> yaml.load("""... !!python/object:__main__.Hero... name: Welthyr Syxgon... hp: 1200... sp: 0... """)
Hero(name='Welthyr Syxgon', hp=1200, sp=0)
注意,构造任意Python对象的能力可能是危险的如果你收到来自不受信任来源的YAML文件如互联网。这个函数 yaml.safe_load限制这种简单的Python对象的能力像整数或列表。
可以标记为安全的python对象,因此被认可 yaml.safe_load。要做到这一点,它来自 yaml.YAMLObject(如部分解释的构造函数,用解析器)和显式地设置它的类属性 yaml_loader来 yaml.SafeLoader.
倾销YAML
的 yaml.dump函数接受一个Python对象,并产生一个YAML文件。
>>>print yaml.dump({'name': 'Silenthand Olleander', 'race': 'Human',
... 'traits': ['ONE_HAND', 'ONE_EYE']})
name: Silenthand Olleander
race: Human
traits: [ONE_HAND, ONE_EYE]
yaml.dump接受第二个可选参数,必须开放的文本或二进制文件。在这种情况下, yaml.dump会产生YAML文件写入该文件。否则, yaml.dump返回产生的文档。
>>> stream =file('document.yaml', 'w')
>>> yaml.dump(data, stream) # Write a YAML representation of data to 'document.yaml'.>>>print yaml.dump(data) # Output the document to the screen.
如果你需要转储几个YAML文件到一个流,使用函数 yaml.dump_all. yaml.dump_all接受一个列表或发电机生产
Python对象序列化为一个YAML文件。第二个可选参数是一个打开的文件。
>>>print yaml.dump([1,2,3], explicit_start=True)
--- [1, 2, 3]
>>>print yaml.dump_all([1,2,3], explicit_start=True)
---1---2---3
你甚至可能抛售Python类的实例。
>>>class Hero:
... def__init__(self, name, hp, sp):
... self.name = name
... self.hp = hp
... self.sp = sp
... def__repr__(self):
... return"%s(name=%r, hp=%r, sp=%r)"% (
... self.__class__.__name__, self.name, self.hp, self.sp)
>>>print yaml.dump(Hero("Galain Ysseleg", hp=-3, sp=2))
!!python/object:__main__.Hero {hp: -3, name: Galain Ysseleg, sp: 2}
yaml.dump支持许多关键字参数指定格式细节的排放国。例如,您可以设置首选intendation和宽度,使用武力规范化YAML格式或首选风格标量和集合。
>>>print yaml.dump(range(50))
[0, 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]
>>>print yaml.dump(range(50), width=50, indent=4)
[0, 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]
>>>print yaml.dump(range(5), canonical=True)
---!!seq [
!!int"0",
!!int"1",
!!int"2",
!!int"3",
!!int"4",
]
>>>print yaml.dump(range(5), default_flow_style=False)
-0-1-2-3-4>>>print yaml.dump(range(5), default_flow_style=True, default_style='"')
[!!int"0", !!int"1", !!int"2", !!int"3", !!int"4"]
构造函数、用解析器
你可以定义自己的特定于应用程序的标记。最简单的方法是定义一个子类 yaml.YAMLObject:
>>>class Monster(yaml.YAMLObject):
... yaml_tag =u'!Monster'
... def__init__(self, name, hp, ac, attacks):
... self.name = name
... self.hp = hp
... self.ac = ac
... self.attacks = attacks
... def__repr__(self):
... return"%s(name=%r, hp=%r, ac=%r, attacks=%r)"% (
... self.__class__.__name__, self.name, self.hp, self.ac, self.attacks)
上面的定义就足以自动加载和转储 Monster对象:
>>> yaml.load("""... --- !Monster... name: Cave spider... hp: [2,6] # 2d6... ac: 16... attacks: [BITE, HURT]... """)
Monster(name='Cave spider', hp=[2, 6], ac=16, attacks=['BITE', 'HURT'])
>>>print yaml.dump(Monster(
... name='Cave lizard', hp=[3,6], ac=16, attacks=['BITE','HURT']))
!Monster
ac: 16
attacks: [BITE, HURT]
hp: [3, 6]
name: Cave lizard
yaml.YAMLObject使用元类魔法来注册一个构造函数,转换YAML节点类实例,和用,序列化YAML节点的类实例。
如果你不想使用元类,你可以注册你的构造函数和用使用功能 yaml.add_constructor和 yaml.add_representer。例如,您可能想添加一个构造函数,用以下 Dice类:
>>>class Dice(tuple):
... def__new__(cls, a, b):
... returntuple.__new__(cls, [a, b])
... def__repr__(self):
... return"Dice(%s,%s)"%self>>>print Dice(3,6)
Dice(3,6)
的默认表示 Dice对象是不漂亮:
>>>print yaml.dump(Dice(3,6))
!!python/object/new:__main__.Dice
-!!python/tuple [3, 6]
假设你想要一个 Dice对象表示为 AdB在YAML:
>>>print yaml.dump(Dice(3,6))
3d6
首先,我们定义了一个用骰子对象转换为一个标量节点的标签 !dice,那么我们注册它。
>>>def dice_representer(dumper, data):
... return dumper.represent_scalar(u'!dice', u'%sd%s'% data)
>>> yaml.add_representer(Dice, dice_representer)
现在你可能会抛售的一个实例 Dice对象:
>>>print yaml.dump({'gold': Dice(10,6)})
{gold: !dice '10d6'}
让我们构建一个骰子的代码添加对象:
>>>def dice_constructor(loader, node):
... value = loader.construct_scalar(node)
... a, b =map(int, value.split('d'))
... return Dice(a, b)
>>> yaml.add_constructor(u'!dice', dice_constructor)
然后你可以加载 Dice对象:
>>>print yaml.load("""... initial hit points: !dice 8d4... """)
{'initial hit points': Dice(8,4)}
您可能不希望指定标签 !dice无处不在。有一种方法来教PyYAML,任何未加标签的纯标量哪个样子XdY的隐式标签 !dice。使用 add_implicit_resolver:
>>>import re
>>> pattern = re.compile(r'^\d+d\d+$')
>>> yaml.add_implicit_resolver(u'!dice', pattern)
现在你不需要指定标签定义 Dice对象:
>>>print yaml.dump({'treasure': Dice(10,20)})
{treasure: 10d20}
>>>print yaml.load("""... damage: 5d10... """)
{'damage': Dice(5,10)}
YAML的语法
一个好的介绍YAML语法第二章YAML的规范.
你也可以检查YAML食谱。注意,它专注于Ruby实现并使用旧的YAML 1.0语法。
我们现在最常见的YAML一起构造相应的Python对象。
文档
YAML是零个或多个文档的集合。一个空流不包含任何文件。文件是分开的, ---。文档可能选择结束 ...。一个文档可能是也可能不是标注 ---.
一个隐式的文档的例子:
- Multimedia
- Internet
- Education
一个明确的文档的例子:
---- Afterstep
- CTWM
- Oroborus
...
几个文件在同一个流的例子:
---- Ada
- APL
- ASP
- Assembly
- Awk
---- Basic
---- C
- C# # Note that comments are denoted with ' #' (space then #).- C++
- Cold Fusion
块序列
在块背景下,序列条目用 -(缓冲空间):
# YAML- The Dagger 'Narthanc'- The Dagger 'Nimthanc'- The Dagger 'Dethanc'
# Python
["The Dagger 'Narthanc'", "The Dagger 'Nimthanc'", "The Dagger 'Dethanc'"]
可以嵌套块序列:
# YAML-- HTML
- LaTeX
- SGML
- VRML
- XML
- YAML
-- BSD
- GNU Hurd
- Linux
# Python
[['HTML', 'LaTeX', 'SGML', 'VRML', 'XML', 'YAML'], ['BSD', 'GNU Hurd', 'Linux']]
它没有必要开始一个嵌套与一个新行序列:
# YAML- 1.1
- - 2.1
- 2.2
- - - 3.1
- 3.2
- 3.3
# Python
[1.1, [2.1, 2.2], [[3.1, 3.2, 3.3]]]
一块序列可能是一块嵌套映射。请注意,在这种情况下没有必要缩进序列。
# YAMLleft hand:- Ring of Teleportation
- Ring of Speed
right hand:- Ring of Resist Fire
- Ring of Resist Cold
- Ring of Resist Poison
# Python
{'right hand': ['Ring of Resist Fire', 'Ring of Resist Cold', 'Ring of Resist Poison'],
'left hand': ['Ring of Teleportation', 'Ring of Speed']}
块的映射
块的背景下,由键和值的映射 :结肠(空间):
# YAMLbase armor class: 0
base damage:[4,4]plus to-hit: 12
plus to-dam: 16
plus to-ac: 0
# Python
{'plus to-hit': 12, 'base damage': [4, 4], 'base armor class': 0, 'plus to-ac': 0, 'plus to-dam': 16}
复杂的钥匙标有 ?(问号,那么空间):
# YAML
? !!python/tuple [0,0]
: The Hero
? !!python/tuple [0,1]
: Treasure
? !!python/tuple [1,0]
: Treasure
? !!python/tuple [1,1]
: The Dragon
# Python
{(0, 1): 'Treasure', (1, 0): 'Treasure', (0, 0): 'The Hero', (1, 1): 'The Dragon'}
块可以嵌套映射:
# YAMLhero:hp: 34
sp: 8
level: 4
orc:hp: 12
sp: 0
level: 2
# Python
{'hero': {'hp': 34, 'sp': 8, 'level': 4}, 'orc': {'hp': 12, 'sp': 0, 'level': 2}}
一块映射可以嵌套在一个块序列:
# YAML-name: PyYAML
status: 4
license: MIT
language: Python
-name: PySyck
status: 5
license: BSD
language: Python
# Python
[{'status': 4, 'language': 'Python', 'name': 'PyYAML', 'license': 'MIT'},
{'status': 5, 'license': 'BSD', 'name': 'PySyck', 'language': 'Python'}]
流集合
流集合YAML的语法非常接近Python列表和字典的语法构造函数:
# YAML{str:[15, 17], con:[16, 16], dex:[17, 18], wis:[16, 16], int:[10, 13], chr:[5, 8] }
# Python
{'dex': [17, 18], 'int': [10, 13], 'chr': [5, 8], 'wis': [16, 16], 'str': [15, 17], 'con': [16, 16]}
标量
有5个风格的标量YAML:平原,使用单引号,双引号,文字,和折叠:
# YAMLplain: Scroll of Remove Curse
single-quoted:'EASY_KNOW'double-quoted:"?"literal: | # Borrowed from http://www.kersbergen.com/flump/religion.html
by hjw ___
__ /.-.\
/ )_____________\\ Y
/_ /=== == === === =\ _\_
( /)=== == === === == Y \
`-------------------( o )
\___/
folded: >
It removes all ordinary curses from all equipped items.
Heavy or permanent curses are unaffected.
# Python
{'plain': 'Scroll of Remove Curse',
'literal':
'by hjw ___\n'' __ /.-.\\\n'' / )_____________\\\\ Y\n'' /_ /=== == === === =\\ _\\_\n''( /)=== == === === == Y \\\n'' `-------------------( o )\n'' \\___/\n',
'single-quoted': 'EASY_KNOW',
'double-quoted': '?',
'folded': 'It removes all ordinary curses from all equipped items. Heavy or permanent curses are unaffected.\n'}
每个风格都有自己的怪癖。纯标量不使用指标来表示它的开始和结束,因此它是最受限制的风格。其自然属性和参数的应用程序名称。
使用单引号标量,您可以表达任何不包含特殊字符的值。没有转义发生单引用标量除了一对相邻的报价 ''被替换为一个孤独的单引号吗 '.
双引号是最有力的风格和唯一的风格,可以表达任何标量值。双引号标量允许逃离。使用转义序列 \x*和 \u***,你可以表达任何ASCII或Unicode字符。
有两种类型的块标量类型:文字和折叠。大的文字风格是??适合的风格如源代码的文本块。折叠的风格类似于文字风格,但两个相邻非空行是加入一行由一个空格字符分开。
别名
注意,PyYAML还不支持递归的对象。
使用YAML您可能代表任意的对象图表结构。如果你想引用同一个对象从不同部分的文档,您需要使用锚和别名。
锚是用 &指标而用“别名。例如,文档
left hand:&Aname: The Bastard Sword of Eowyn
weight: 30
right hand:*A
表达了一个英雄的想法双手拿着一个沉重的剑。
PyYAML现在完全支持递归的对象。例如,文档
&A[*A]
会产生对象包含一个引用列表本身。
标签
标签是用来表示YAML节点的类型。标准YAML标签定义http://yaml.org/type/index.html.
标签可能是隐式:
boolean: true
integer: 3
float: 3.14
{'boolean': True, 'integer': 3, 'float': 3.14}
或显式:
boolean:!!bool"true"integer:!!int"3"float:!!float"3.14"
{'boolean': True, 'integer': 3, 'float': 3.14}
纯标量没有显式定义的标签是隐式标签的决议。标量值是针对一组正则表达式检查,如果其中一个比赛,相应的标记分配给标量。PyYAML允许应用程序添加自定义隐式标签解析器。
YAML标签和Python类型
下表描述了如何用不同的标记转换为Python对象节点。
YAML标签 Python类型
标准YAML标签
!!null None
!!bool bool
!!int int或 long (int在Python 3)
!!float float
!!binary str (bytes在Python 3)
!!timestamp datetime.datetime
!!omap, !!pairs list的双
!!set set
!!str str或 unicode (str在Python 3)
!!seq list
!!map dict
特定于python的标签
!!python/none None
!!python/bool bool
!!python/bytes (bytes在Python 3)
!!python/str str (str在Python 3)
!!python/unicode unicode (str在Python 3)
!!python/int int
!!python/long long (int在Python 3)
!!python/float float
!!python/complex complex
!!python/list list
!!python/tuple tuple
!!python/dict dict
复杂的Python标签
!!python/name:module.name module.name
!!python/module:package.module package.module
!!python/object:module.cls module.cls实例
!!python/object/new:module.cls module.cls实例
!!python/object/apply:module.f 的价值 f(...)
Python字符串转换(2只)
有四个标签转换为 str和 unicode价值观: !!str, !!binary, !!python/str, !!python/unicode.
!!str标记转化为标量 str如果它的值是ASCII对象。否则它转化为 unicode. !!binary标记转化为标量 str对象的值使用base64编码解码。 !!python/str标量转换为 str对象编码utf - 8编码。 !!python/unicode标量转换为 unicode对象。
相反,一个 str对象转换为1。一个 !!str如果它的值是ASCII标量。2。一个 !!python/str如果它的值是一个正确的utf - 8序列标量。3所示。一个 !!binary否则标量。
一个 unicode对象转换为1。一个 !!python/unicode如果它的值是ASCII标量。2。一个 !!str否则标量。
Python字符串转换(3只)
在Python 3中, str对象转换为 !!str标量和 bytes??象 !!binary标量。由于兼容性原因,标签 !!python/str和 !!python/unicode仍然支持和转换成吗 str对象。
名称和模块
为了表示静态的Python对象像函数或类,您需要使用一个复杂的 !!python/name标签。例如,函数 yaml.dump可以表示成
!!python/name:yaml.dump
同样,模块使用标签表示 !python/module:
!!python/module:yaml
对象
任何可以序列化pickleable对象使用 !!python/object标签:
!!python/object:module.Class{attribute: value, ... }
为了支持泡菜协议,两个额外的形式的 !!python/object提供标签:
!!python/object/new:module.Classargs:[argument, ...]kwds:{key: value, ...}state: ...
listitems:[item, ...]dictitems:[key: value, ...]
!!python/object/apply:module.function
args:[argument, ...]kwds:{key: value, ...}state: ...
listitems:[item, ...]dictitems:[key: value, ...]
如果只 args可以缩短字段非空,上面的记录:
!!python/object/new:module.Class[argument, ...]!!python/object/apply:module.function[argument, ...]
参考
警告:API的稳定性不能保证!
yaml包
scan(stream, Loader=Loader)
scan(stream)扫描给 stream并产生一系列的令牌。
parse(stream, Loader=Loader)
emit(events, stream=None, Dumper=Dumper,
canonical=None,
indent=None,
width=None,
allow_unicode=None,
line_break=None)
parse(stream)解析给定的 stream并产生一个解析事件序列。
emit(events, stream=None)序列化给定序列的解析 events和写他们 stream。如果 stream是 None,它返回生产流。
compose(stream, Loader=Loader)
compose_all(stream, Loader=Loader)
serialize(node, stream=None, Dumper=Dumper,
encoding='utf-8', # encoding=None (Python 3)
explicit_start=None,
explicit_end=None,
version=None,
tags=None,
canonical=None,
indent=None,
width=None,
allow_unicode=None,
line_break=None)
serialize_all(nodes, stream=None, Dumper=Dumper, ...)
compose(stream)解析给定的 stream并返回的根表示图中的第一个文档流。如果没有文件流,它的回报 None.
compose_all(stream)解析给定的 stream并返回一个表示序列图对应的文件流。
serialize(node, stream=None)序列化到给定的表示图 stream。如果 stream是 None,它返回生产流。
serialize_all(node, stream=None)序列化给定表示图形的序列 stream。如果 stream是 None,它返回生产流。
load(stream, Loader=Loader)
load_all(stream, Loader=Loader)
safe_load(stream)
safe_load_all(stream)
dump(data, stream=None, Dumper=Dumper,
default_style=None,
default_flow_style=None,
encoding='utf-8', # encoding=None (Python 3)
explicit_start=None,
explicit_end=None,
version=None,
tags=None,
canonical=None,
indent=None,
width=None,
allow_unicode=None,
line_break=None)
dump_all(data, stream=None, Dumper=Dumper, ...)
safe_dump(data, stream=None, ...)
safe_dump_all(data, stream=None, ...)
load(stream)解析给定的 stream并返回一个Python对象由第一文档流。如果没有文件流,它的回报 None.
load_all(stream)解析给定的 stream并返回一个Python对象序列对应的文件流。
safe_load(stream)解析给定的 stream并返回一个Python对象由第一文档流。如果没有文件流,它的回报 None. safe_load只认定标准YAML标签和不能构造任意Python对象。
可以标记为安全的python对象,因此被认可 yaml.safe_load。要做到这一点,它来自 yaml.YAMLObject(如部分解释的构造函数,用解析器)和显式地设置它的类属性 yaml_loader来 yaml.SafeLoader.
safe_load_all(stream)解析给定的 stream并返回一个Python对象序列对应的文件流。 safe_load_all只认定标准YAML标签和不能构造任意Python对象。
dump(data, stream=None)由于Python对象序列化到 stream。如果 stream是 None,它返回生产流。
dump_all(data, stream=None)序列化给定的Python对象序列 stream。如果 stream是 None,它返回生产流。每个对象表示为YAML文件。
safe_dump(data, stream=None)由于Python对象序列化到 stream。如果 stream是 None,它返回生产流。 safe_dump只生产标准YAML标签并不能代表任意Python对象。
safe_dump_all(data, stream=None)序列化给定的Python对象序列 stream。如果 stream是 None,它返回生产流。每个对象表示为YAML文件。 safe_dump_all只生产标准YAML标签并不能代表任意Python对象。
def constructor(loader, node):
# ...return data
def multi_constructor(loader, tag_suffix, node):
# ...return data
add_constructor(tag, constructor, Loader=Loader)
add_multi_constructor(tag_prefix, multi_constructor, Loader=Loader)
add_constructor(tag, constructor)指定一个 constructor对于给定的 tag。构造函数是一个函数,将YAML的节点表示图转换为本机Python对象。构造函数接受的一个实例 Loader和一个节点,并返回一个Python对象。
add_multi_constructor(tag_prefix, multi_constructor)指定一个 multi_constructor对于给定的 tag_prefix。multi-constructor是一个函数,将YAML的节点表示图转换为本机Python对象。一个multi-constructor接受的一个实例 Loader节点的后缀标签,一个节点,并返回一个Python对象。
def representer(dumper, data):
# ...return node
def multi_representer(dumper, data):
# ...return node
add_representer(data_type, representer, Dumper=Dumper)
add_multi_representer(base_data_type, multi_representer, Dumper=Dumper)
add_representer(data_type, representer)指定一个 representer给定的Python对象 data_type。用是一个函数,将本机Python对象转换为一个节点的YAML表示图。一个正在接受的一个实例 Dumper和一个对象,并返回一个节点。
add_multi_representer(base_data_type, multi_representer)指定一个 multi_representer给定的Python对象 base_data_type或它的任何子类。multi-representer是一个函数,将一个本机Python对象转换为节点的YAML表示图。一个multi-representer接受的一个实例 Dumper和一个对象,并返回一个节点。
add_implicit_resolver(tag, regexp, first, Loader=Loader, Dumper=Dumper)
add_path_resolver(tag, path, kind, Loader=Loader, Dumper=Dumper)
add_implicit_resolver(tag, regexp, first)增加了一个隐式标签解析器为纯标量。如果给定的标量值相匹配 regexp,它是分配 tag. first列出可能的初始字符或 None.
add_path_resolver(tag, path, kind)添加一个基于路径隐式标签解析器。一个 path键的列表形式的路径图中的一个节点表示。路径元素可以字符串值、整数或 None。的 kind的一个节点 str, list, dict,或 None.
马克
Mark(name, index, line, column, buffer, pointer)
的一个实例 Mark指向一个输入流中的某些位置。 name流的名称,比如它可能是文件名是否文件输入流。 line和 column行和列的位置(从0开始)。 buffer,当它不是 None输入流的一部分,包含位置和 pointer指的是位置 buffer.
YAMLError
YAMLError()
如果YAML解析器遇到一个错误条件,它提出了一个例外的一个实例 YAMLError或者它的子类。一个应用程序可能会捕捉这个异常和警告用户。
try:
config = yaml.load(file('config.yaml', 'r'))
except yaml.YAMLError, exc:
print"Error in configuration file:", exc
YAML产生的异常处理器可能指向问题的位置。
>>>try:
... yaml.load("unbalanced blackets: ][")
... except yaml.YAMLError, exc:
... ifhasattr(exc, 'problem_mark'):
... mark = exc.problem_mark
... print"Error position: (%s:%s)"% (mark.line+1, mark.column+1)
Error position: (1:22)
令牌
令牌是由YAML扫描仪。他们不是真正有用的除了低级YAML语法高亮等应用程序。
PyYAML扫描仪产生以下类型的令牌:
StreamStartToken(encoding, start_mark, end_mark) # Start of the stream.
StreamEndToken(start_mark, end_mark) # End of the stream.
DirectiveToken(name, value, start_mark, end_mark) # YAML directive, either %YAML or %TAG.
DocumentStartToken(start_mark, end_mark) # '---'.
DocumentEndToken(start_mark, end_mark) # '...'.
BlockSequenceStartToken(start_mark, end_mark) # Start of a new block sequence.
BlockMappingStartToken(start_mark, end_mark) # Start of a new block mapping.
BlockEndToken(start_mark, end_mark) # End of a block collection.
FlowSequenceStartToken(start_mark, end_mark) # '['.
FlowMappingStartToken(start_mark, end_mark) # '{'.
FlowSequenceEndToken(start_mark, end_mark) # ']'.
FlowMappingEndToken(start_mark, end_mark) # '}'.
KeyToken(start_mark, end_mark) # Either '?' or start of a simple key.
ValueToken(start_mark, end_mark) # ':'.
BlockEntryToken(start_mark, end_mark) # '-'.
FlowEntryToken(start_mark, end_mark) # ','.
AliasToken(value, start_mark, end_mark) # '*value'.
AnchorToken(value, start_mark, end_mark) # '&value'.
TagToken(value, start_mark, end_mark) # '!value'.
ScalarToken(value, plain, style, start_mark, end_mark) # 'value'.
start_mark和 end_mark表示的开始和结束标记。
例子:
>>> document ="""... ---... block sequence:... - BlockEntryToken... block mapping:... ? KeyToken... : ValueToken... flow sequence: [FlowEntryToken, FlowEntryToken]... flow mapping: {KeyToken: ValueToken}... anchors and tags:... - &A !!int '5'... - *A... ...... """>>>for token in yaml.scan(document):
... print token
StreamStartToken(encoding='utf-8')
DocumentStartToken()
BlockMappingStartToken()
KeyToken()
ScalarToken(plain=True, style=None, value=u'block sequence')
ValueToken()
BlockEntryToken()
ScalarToken(plain=True, style=None, value=u'BlockEntryToken')
KeyToken()
ScalarToken(plain=True, style=None, value=u'block mapping')
ValueToken()
BlockMappingStartToken()
KeyToken()
ScalarToken(plain=True, style=None, value=u'KeyToken')
ValueToken()
ScalarToken(plain=True, style=None, value=u'ValueToken')
BlockEndToken()
KeyToken()
ScalarToken(plain=True, style=None, value=u'flow sequence')
ValueToken()
FlowSequenceStartToken()
ScalarToken(plain=True, style=None, value=u'FlowEntryToken')
FlowEntryToken()
ScalarToken(plain=True, style=None, value=u'FlowEntryToken')
FlowSequenceEndToken()
KeyToken()
ScalarToken(plain=True, style=None, value=u'flow mapping')
ValueToken()
FlowMappingStartToken()
KeyToken()
ScalarToken(plain=True, style=None, value=u'KeyToken')
ValueToken()
ScalarToken(plain=True, style=None, value=u'ValueToken')
FlowMappingEndToken()
KeyToken()
ScalarToken(plain=True, style=None, value=u'anchors and tags')
ValueToken()
BlockEntryToken()
AnchorToken(value=u'A')
TagToken(value=(u'!!', u'int'))
ScalarToken(plain=False, style="'", value=u'5')
BlockEntryToken()
AliasToken(value=u'A')
BlockEndToken()
DocumentEndToken()
StreamEndToken()
事件
事件由底层的解析器和发射器的接口,使用类似于SAX API。当解析器解析YAML流并产生一系列事件,发射器接受一系列事件和发出YAML流。
以下事件定义:
StreamStartEvent(encoding, start_mark, end_mark)
StreamEndEvent(start_mark, end_mark)
DocumentStartEvent(explicit, version, tags, start_mark, end_mark)
DocumentEndEvent(start_mark, end_mark)
SequenceStartEvent(anchor, tag, implicit, flow_style, start_mark, end_mark)
SequenceEndEvent(start_mark, end_mark)
MappingStartEvent(anchor, tag, implicit, flow_style, start_mark, end_mark)
MappingEndEvent(start_mark, end_mark)
AliasEvent(anchor, start_mark, end_mark)
ScalarEvent(anchor, tag, implicit, value, style, start_mark, end_mark)
的 flow_style国旗表明如果一组块或流。可能的值是 None, True, False。的 style一个标量旗事件表示标量的风格。可能的值是 None, _, '\_, '"', '|', '>'。的 implicit集合的旗帜开始事件表明如果标签收集排放时可以省略。的 implicit标量旗事件是一个布尔值,表示如果标签时可以省略标量在平原和non-plain发出相应的风格。
例子:
>>> document ="""... scalar: &A !!int '5'... alias: *A... sequence: [1, 2, 3]... mapping: [1: one, 2: two, 3: three]... """>>>for event in yaml.parse(document):
... print event
StreamStartEvent()
DocumentStartEvent()
MappingStartEvent(anchor=None, tag=None, implicit=True)
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'scalar')
ScalarEvent(anchor=u'A', tag=u'tag:yaml.org,2002:int', implicit=(False, False), value=u'5')
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'alias')
AliasEvent(anchor=u'A')
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'sequence')
SequenceStartEvent(anchor=None, tag=None, implicit=True)
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'1')
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'2')
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'3')
SequenceEndEvent()
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'mapping')
MappingStartEvent(anchor=None, tag=None, implicit=True)
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'1')
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'one')
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'2')
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'two')
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'3')
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'three')
MappingEndEvent()
MappingEndEvent()
DocumentEndEvent()
StreamEndEvent()
>>>print yaml.emit([
... yaml.StreamStartEvent(encoding='utf-8'),
... yaml.DocumentStartEvent(explicit=True),
... yaml.MappingStartEvent(anchor=None, tag=u'tag:yaml.org,2002:map', implicit=True, flow_style=False),
... yaml.ScalarEvent(anchor=None, tag=u'tag:yaml.org,2002:str', implicit=(True, True), value=u'agile languages'),
... yaml.SequenceStartEvent(anchor=None, tag=u'tag:yaml.org,2002:seq', implicit=True, flow_style=True),
... yaml.ScalarEvent(anchor=None, tag=u'tag:yaml.org,2002:str', implicit=(True, True), value=u'Python'),
... yaml.ScalarEvent(anchor=None, tag=u'tag:yaml.org,2002:str', implicit=(True, True), value=u'Perl'),
... yaml.ScalarEvent(anchor=None, tag=u'tag:yaml.org,2002:str', implicit=(True, True), value=u'Ruby'),
... yaml.SequenceEndEvent(),
... yaml.MappingEndEvent(),
... yaml.DocumentEndEvent(explicit=True),
... yaml.StreamEndEvent(),
... ])
---
agile languages: [Python, Perl, Ruby]
...
节点
YAML中节点的实体信息模型。有三种节点:标量,序列和映射。在PyYAML,节点是由作曲家和可以序列化的YAML流序列化器。
ScalarNode(tag, value, style, start_mark, end_mark)
SequenceNode(tag, value, flow_style, start_mark, end_mark)
MappingNode(tag, value, flow_style, start_mark, end_mark)
的 style和 flow_style至于事件标记有相同的意义。一个标量节点的值必须是一个unicode字符串。的价值序列节点的节点列表。一个映射节点的值是一个列表的键和值组成的双节点。
例子:
>>>print yaml.compose("""... kinds:... - scalar... - sequence... - mapping... """)
MappingNode(tag=u'tag:yaml.org,2002:map', value=[
(ScalarNode(tag=u'tag:yaml.org,2002:str', value=u'kinds'), SequenceNode(tag=u'tag:yaml.org,2002:seq', value=[
ScalarNode(tag=u'tag:yaml.org,2002:str', value=u'scalar'),
ScalarNode(tag=u'tag:yaml.org,2002:str', value=u'sequence'),
ScalarNode(tag=u'tag:yaml.org,2002:str', value=u'mapping')]))])
>>>print yaml.serialize(yaml.SequenceNode(tag=u'tag:yaml.org,2002:seq', value=[
... yaml.ScalarNode(tag=u'tag:yaml.org,2002:str', value=u'scalar'),
... yaml.ScalarNode(tag=u'tag:yaml.org,2002:str', value=u'sequence'),
... yaml.ScalarNode(tag=u'tag:yaml.org,2002:str', value=u'mapping')]))
- scalar
- sequence
- mapping
加载程序
Loader(stream)
SafeLoader(stream)
BaseLoader(stream)
# The following classes are available only if you build LibYAML bindings.
CLoader(stream)
CSafeLoader(stream)
CBaseLoader(stream)
Loader(stream)以上是最常见的类和应该在大多数情况下使用。 stream是一个输入YAML流。它可以是一个字符串,Unicode字符串,一个打开的文件,一个开放的Unicode文件。
Loader支持所有预定义的标记和可能构造任意Python对象。因此它不安全 Loader加载文档收到一个不可信的来源。默认情况下,这个功能 scan, parse, compose, construct,和其他人使用 Loader.
SafeLoader(stream)仅支持标准YAML标签,因此它不可能构造类实例和安全使用文档收到一个不可信的来源。的函数 safe_load和 safe_load_all使用 SafeLoader解析一个流。
BaseLoader(stream)不解决或支持任何标签和构建只有基本的Python对象:列表、字典和Unicode字符串。
CLoader, CSafeLoader, CBaseLoader以上版本的类用C编写使用吗LibYAML图书馆。
Loader.check_token(*TokenClasses)
Loader.peek_token()
Loader.get_token()
Loader.check_token(*TokenClasses)返回 True如果下一个记号流是一个给定的实例 TokenClasses。否则它会返回 False.
Loader.peek_token()返回下一个记号流,但不删除它从内部标记队列。函数返回 None结束的时候流。
Loader.get_token()返回下一个记号流和删除它从内部标记队列。函数返回 None结束的时候流。
Loader.check_event(*EventClasses)
Loader.peek_event()
Loader.get_event()
Loader.check_event(*EventClasses)返回 True如果下一个事件流是一个给定的实例 EventClasses。否则它会返回 False.
Loader.peek_event()返回下一个事件流,但不删除它从内部事件队列。函数返回 None结束的时候流。
Loader.get_event()返回下一个事件流和从内部事件队列中删除它。函数返回 None结束的时候流。
Loader.check_node()
Loader.get_node()
Loader.check_node()返回 True有更多的文档流中可用。否则它会返回 False.
Loader.get_node()构造的图表示流中的下一个文档,并返回它的根节点。
Loader.check_data()
Loader.get_data()
Loader.add_constructor(tag, constructor) # Loader.add_constructor is a class method.
Loader.add_multi_constructor(tag_prefix, multi_constructor) # Loader.add_multi_constructor is a class method.
Loader.construct_scalar(node)
Loader.construct_sequence(node)
Loader.construct_mapping(node)
Loader.check_data()返回 True有更多的文档流中可用。否则它会返回 False.
Loader.get_data()构造并返回一个Python对象对应的下一个文档流。
Loader.add_constructor(tag, constructor):看 add_constructor.
Loader.add_multi_constructor(tag_prefix, multi_constructor):看 add_multi_constructor.
Loader.construct_scalar(node)检查给定 node是一个标量和返回其值。这个函数是在构造函数中使用。
Loader.construct_sequence(node)检查给定 node是一个序列,并返回一个Python对象节点对应的商品列表。这个函数是在构造函数中使用。
Loader.construct_mapping(node)检查给定 node字典是一个映射,并返回一个Python对象对应节点的键和值。这个函数是在构造函数中使用。
Loader.add_implicit_resolver(tag, regexp, first) # Loader.add_implicit_resolver is a class method.
Loader.add_path_resolver(tag, path, kind) # Loader.add_path_resolver is a class method.
Loader.add_implicit_resolver(tag, regexp, first):看 add_implicit_resolver.
Loader.add_path_resolver(tag, path, kind):看 add_path_resolver.
自动倾卸车
Dumper(stream,
default_style=None,
default_flow_style=None,
canonical=None,
indent=None,
width=None,
allow_unicode=None,
line_break=None,
encoding=None,
explicit_start=None,
explicit_end=None,
version=None,
tags=None)
SafeDumper(stream, ...)
BaseDumper(stream, ...)
# The following classes are available only if you build LibYAML bindings.
CDumper(stream, ...)
CSafeDumper(stream, ...)
CBaseDumper(stream, ...)
Dumper(stream)以上是最常见的类和应该在大多数情况下使用。 stream是一个输出YAML流。它可以是一个打开的文件或开放的Unicode文件。
Dumper支持所有预定义的标记和可能代表任意Python对象。因此它可能产生的文档不能加载其他YAML处理器。默认情况下,这个功能 emit, serialize, dump,和其他人使用 Dumper.
SafeDumper(stream)只生产标准YAML标签,因此不能代表类实例,可能更兼容其他YAML处理器。的函数 safe_dump和 safe_dump_all使用 SafeDumper产生一个YAML文件。
BaseDumper(stream)不支持任何标签,只适用于子类化。
CDumper, CSafeDumper, CBaseDumper以上版本的类用C编写使用吗LibYAML图书馆。
Dumper.emit(event)
Dumper.emit(event)序列化给定的 event并将其写入输出流。
Dumper.open()
Dumper.serialize(node)
Dumper.close()
Dumper.open()发出 StreamStartEvent.
Dumper.serialize(node)序列化的表示图到输出流中。
Dumper.close()发出 StreamEndEvent.
Dumper.represent(data)
Dumper.add_representer(data_type, representer) # Dumper.add_representer is a class method.
Dumper.add_multi_representer(base_data_type, multi_representer) # Dumper.add_multi_representer is a class method.
Dumper.represent_scalar(tag, value, style=None)
Dumper.represent_sequence(tag, value, flow_style=None)
Dumper.represent_mapping(tag, value, flow_style=None)
Dumper.represent(data)给定的Python对象序列化到输出YAML流。
Dumper.add_representer(data_type, representer):看 add_representer.
Dumper.add_multi_representer(base_data_type, multi_representer):看 add_multi_representer.
Dumper.represent_scalar(tag, value, style=None)返回一个标量与给定的节点 tag, value, style。这个函数是用于表示??
Dumper.represent_sequence(tag, sequence, flow_style=None)返回一个与给定序列节点 tag和子节点生成的项目 sequence.
Dumper.represent_mapping(tag, mapping, flow_style=None)返回一个与给定映射节点 tag和子节点生成的键和值 mapping.
Dumper.add_implicit_resolver(tag, regexp, first) # Dumper.add_implicit_resolver is a class method.
Dumper.add_path_resolver(tag, path, kind) # Dumper.add_path_resolver is a class method.
Dumper.add_implicit_resolver(tag, regexp, first):看 add_implicit_resolver.
Dumper.add_path_resolver(tag, path, kind):看 add_path_resolver.
YAMLObject
class MyYAMLObject(YAMLObject):
yaml_loader = Loader
yaml_dumper = Dumper
yaml_tag =u'...'
yaml_flow_style = ...
@classmethoddef from_yaml(cls, loader, node):
# ...return data
@classmethoddef to_yaml(cls, dumper, data):
# ...return node
子类化 YAMLObject是一种简单的方法来定义标签、构造函数和用你的类。你只需要覆盖 yaml_tag属性。如果你想定义您的自定义构造函数和用,重新定义 from_yaml和 to_yaml相应的方法。
偏离规范
这一部分需要更新
YAML的标签规则混乱。我们很近,但是没有。也许规范和解析器应该是固定的。无论如何,最好的规则在YAML标签是不使用它们。
字节顺序标记。最初的BOM是剥夺,但BOM在流被认为是部分的内容。它可以是固定的,但现在真的不重要。
不允许空纯标量如果指定别名或标记。这样做是为了防止anomalities像!标签,价值,既可以解释[!值]和[!”,“价值”]。规范应该是固定的。
缩进流的集合。规范需要缩进他们比他们的父节点。不幸的是这个规则呈现许多直观正确的构造是无效的,例如,
block: {
========================================================================
ConfigParser模块
用于生成和修改常见配置文档,当前模块的名称在 python 3.x 版本中变更为 configparser。
来看一个好多软件的常见文档格式如下
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
[bitbucket.org]
User = hg
[topsecret.server.com]
Port = 50022
ForwardX11 = no
如果想用python生成一个这样的文档怎么做呢?
import configparser
config = configparser.ConfigParser()
config["DEFAULT"] = {'ServerAliveInterval': '45',
'Compression': 'yes',
'CompressionLevel': '9'}
config['bitbucket.org'] = {} ----------------------- value先写为空,后面再填。
config['bitbucket.org']['User'] = 'hg'
config['topsecret.server.com'] = {}
topsecret = config['topsecret.server.com']
topsecret['Host Port'] = '50022' # mutates the parser
topsecret['ForwardX11'] = 'no' # same here
config['DEFAULT']['ForwardX11'] = 'yes'
with open('example.ini', 'w') as configfile:
config.write(configfile)
写完了还可以再读出来哈。
>>> import configparser
>>> config = configparser.ConfigParser()
>>> config.sections()
[]
>>> config.read('example.ini')
['example.ini']
>>> config.sections()
['bitbucket.org', 'topsecret.server.com']
>>> 'bitbucket.org' in config
True
>>> 'bytebong.com' in config
False
>>> config['bitbucket.org']['User']
'hg'
>>> config['DEFAULT']['Compression']
'yes'
>>> topsecret = config['topsecret.server.com']
>>> topsecret['ForwardX11']
'no'
>>> topsecret['Port']
'50022'
>>> for key in config['bitbucket.org']: print(key)
...
user
compressionlevel
serveraliveinterval
compression
forwardx11
>>> config['bitbucket.org']['ForwardX11']
'yes'
configparser增删改查语法
[section1]
k1 = v1
k2:v2
[section2]
k1 = v1
import ConfigParser
config = ConfigParser.ConfigParser()
config.read('i.cfg')
# ########## 读 ##########
#secs = config.sections()
#print secs
#options = config.options('group2')
#print options
#item_list = config.items('group2')
#print item_list
#val = config.get('group1','key')
#val = config.getint('group1','key')
# ########## 改写 ##########
#sec = config.remove_section('group1')
#config.write(open('i.cfg', "w"))
#sec = config.has_section('wupeiqi')
#sec = config.add_section('wupeiqi')
#config.write(open('i.cfg', "w"))
#config.set('group2','k1',11111)
#config.write(open('i.cfg', "w"))
#config.remove_option('group2','age')
#config.write(open('i.cfg', "w"))
=======================================================================================
hashlib模块
用于加密相关的操作,3.x里代替了2.x里面的md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法,SHA比md5更安全。
应用:网站防篡改。定时的wget首页,md5后比较是否改变。
import hashlib
m = hashlib.md5()
m.update(b"Hello")
m.update(b"It's me")
print(m.digest())
m.update(b"It's been a long time since last time we ...")
print(m.digest()) #2进制格式hash
print(len(m.hexdigest())) #16进制格式hash
'''
def digest(self, *args, **kwargs): # real signature unknown
""" Return the digest value as a string of binary data. """
pass
def hexdigest(self, *args, **kwargs): # real signature unknown
""" Return the digest value as a string of hexadecimal digits. """
pass
'''
中文字符串的处理方式:
import hashlib
m2 = hashlib.md5()
m2.update("SFJLSJ但是减肥路上的肌肤".encode(encoding='utf-8'))
print(m2.hexdigest())
import hashlib =============== hashlib支持中文
# ######## md5 ########
hash = hashlib.md5()
hash.update('admin')
print(hash.hexdigest())
# ######## sha1 ########
hash = hashlib.sha1()
hash.update('admin')
print(hash.hexdigest())
# ######## sha256 ########
hash = hashlib.sha256()
hash.update('admin')
print(hash.hexdigest())
# ######## sha384 ########
hash = hashlib.sha384()
hash.update('admin')
print(hash.hexdigest())
# ######## sha512 ########
hash = hashlib.sha512()
hash.update('admin')
print(hash.hexdigest())
还不够吊?python 还有一个 hmac 模块,它内部对我们创建 key 和 内容 再进行处理然后再加密
散列消息鉴别码,简称HMAC,是一种基于消息鉴别码MAC(Message Authentication Code)的鉴别机制。使用HMAC时,消息通讯的双方,通过验证消息中加入的鉴别密钥K来鉴别消息的真伪;
一般用于网络通信中消息加密,前提是双方先要约定好key,就像接头暗号一样,然后消息发送把用key把消息加密,接收方用key + 消息明文再加密,拿加密后的值 跟 发送者的相对比是否相等,这样就能验证消息的真实性,及发送者的合法性了。
import hmac
h = hmac.new(b'天王盖地虎'.endode(endoding='utf-8'), b'宝塔镇河妖'.encode(encoding='utf-8')) -----会报错,
print(h.gigest()) ---------> 十进制的加密
print(h.hexdigest()) ----------》 十六进制的加密
更多关于md5,sha1,sha256等介绍的文章看这里https://www.tbs-certificates.co.uk/FAQ/en/sha256.html
常用subprocess方法示例
#执行命令,返回命令执行状态 , 0 or 非0
>>> retcode = subprocess.call(["ls", "-l"])
#执行命令,如果命令结果为0,就正常返回,否则抛异常
>>> subprocess.check_call(["ls", "-l"])
0
#接收字符串格式命令,返回元组形式,第1个元素是执行状态,第2个是命令结果
>>> subprocess.getstatusoutput('ls /bin/ls')
(0, '/bin/ls')
#接收字符串格式命令,并返回结果
>>> subprocess.getoutput('ls /bin/ls')
'/bin/ls'
#执行命令,并返回结果,注意是返回结果,不是打印,下例结果返回给res
>>> res=subprocess.check_output(['ls','-l'])
>>> res
b'total 0\ndrwxr-xr-x 12 alex staff 408 Nov 2 11:05 OldBoyCRM\n'
#上面那些方法,底层都是封装的subprocess.Popen
poll()
Check if child process has terminated. Returns returncode
wait()
Wait for child process to terminate. Returns returncode attribute.
terminate() 杀掉所启动进程
communicate() 等待任务结束
stdin 标准输入
stdout 标准输出
stderr 标准错误
pid
The process ID of the child process.
#例子
>>> p = subprocess.Popen("df -h|grep disk",stdin=subprocess.PIPE,stdout=subprocess.PIPE,shell=True)
>>> p.stdout.read()
b'/dev/disk1 465Gi 64Gi 400Gi 14% 16901472 104938142 14% /\n'
>>> 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.run(...)是推荐的常用方法,在大多数情况下能满足需求,但如果你可能需要进行一些复杂的与系统的交互的话,你还可以用subprocess.Popen(),语法如下:
p = subprocess.Popen("find / -size +1000000 -exec ls -shl {} \;",shell=True,stdout=subprocess.PIPE)
print(p.stdout.read())
可用参数:
args:shell命令,可以是字符串或者序列类型(如:list,元组)
bufsize:指定缓冲。0 无缓冲,1 行缓冲,其他 缓冲区大小,负值 系统缓冲
stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
preexec_fn:只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用
close_sfs:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会继承父进程的输入、输出、错误管道。
所以不能将close_fds设置为True同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。
shell:同上
cwd:用于设置子进程的当前目录
env:用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。
universal_newlines:不同系统的换行符不同,True -> 同意使用 \n
startupinfo与createionflags只在windows下有效
将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等
终端输入的命令分为两种:
输入即可得到输出,如:ifconfig
输入进行某环境,依赖再输入,如:python
需要交互的命令示例
import subprocess
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 ')
obj.stdin.write('print 4 \n ')
out_error_list = obj.communicate(timeout=10)
print out_error_list
subprocess实现sudo 自动输入密码
import subprocess
def mypass():
mypass = '123' #or get the password from anywhere
return mypass
echo = subprocess.Popen(['echo',mypass()],
stdout=subprocess.PIPE,
)
sudo = subprocess.Popen(['sudo','-S','iptables','-L'],
stdin=echo.stdout,
stdout=subprocess.PIPE,
)
end_of_pipe = sudo.stdout
print "Password ok \n Iptables Chains %s" % end_of_pipe.read()
====================================================================================================
logging模块
很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误、警告等信息输出,python的logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,logging的日志可以分为 debug(), info(), warning(), error() and critical() 5个级别,下面我们看一下怎么用。
最简单用法
import logging
logging.warning("user [alex] attempted wrong password more than 3 times")
logging.critical("server is down")
#输出
WARNING:root:user [alex] attempted wrong password more than 3 times
CRITICAL:root:server is down
看一下这几个日志级别分别代表什么意思
Level When it’s used
DEBUG Detailed information, typically of interest only when diagnosing problems.
INFO Confirmation that things are working as expected.
WARNING An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected.
ERROR Due to a more serious problem, the software has not been able to perform some function.
CRITICAL A serious error, indicating that the program itself may be unable to continue running.
如果想把日志写到文件里,也很简单
import logging
logging.basicConfig(filename='example.log',level=logging.INFO)
logging.debug('This message should go to the log file')
logging.info('So should this')
logging.warning('And this, too')
其中下面这句中的level=loggin.INFO意思是,把日志纪录级别设置为INFO,也就是说,只有比日志是INFO或比INFO级别更高的日志才会被纪录到文件里,在这个例子, 第一条日志是不会被纪录的,如果希望纪录debug的日志,那把日志级别改成DEBUG就行了。
logging.basicConfig(filename='example.log',level=logging.INFO)
感觉上面的日志格式忘记加上时间啦,日志不知道时间怎么行呢,下面就来加上!
import logging
logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
logging.warning('is when this event was logged.')
#输出
12/12/2010 11:46:36 AM is when this event was logged.
日志格式
%(name)s
Logger的名字
%(levelno)s
数字形式的日志级别
%(levelname)s
文本形式的日志级别
%(pathname)s
调用日志输出函数的模块的完整路径名,可能没有
%(filename)s
调用日志输出函数的模块的文件名
%(module)s
调用日志输出函数的模块名
%(funcName)s
调用日志输出函数的函数名
%(lineno)d
调用日志输出函数的语句所在的代码行
%(created)f
当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d
输出日志信息时的,自Logger创建以 来的毫秒数
%(asctime)s
字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(thread)d
线程ID。可能没有
%(threadName)s
线程名。可能没有
%(process)d
进程ID。可能没有
%(message)s
用户输出的消息
如果想同时把log打印在屏幕和文件日志里,就需要了解一点复杂的知识 了
Python 使用logging模块记录日志涉及四个主要类,使用官方文档中的概括最为合适:
logger提供了应用程序可以直接使用的接口;
handler将(logger创建的)日志记录发送到合适的目的输出;
filter提供了细度设备来决定输出哪条日志记录;
formatter决定日志记录的最终输出格式。
logger
每个程序在输出信息之前都要获得一个Logger。Logger通常对应了程序的模块名,比如聊天工具的图形界面模块可以这样获得它的Logger:
LOG=logging.getLogger(”chat.gui”)
而核心模块可以这样:
LOG=logging.getLogger(”chat.kernel”)
Logger.setLevel(lel):指定最低的日志级别,低于lel的级别将被忽略。debug是最低的内置级别,critical为最高
Logger.addFilter(filt)、Logger.removeFilter(filt):添加或删除指定的filter
Logger.addHandler(hdlr)、Logger.removeHandler(hdlr):增加或删除指定的handler
Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical():可以设置的日志级别
handler
handler对象负责发送相关的信息到指定目的地。Python的日志系统有多种Handler可以使用。有些Handler可以把信息输出到控制台,有些Logger可以把信息输出到文件,还有些 Handler可以把信息发送到网络上。如果觉得不够用,还可以编写自己的Handler。可以通过addHandler()方法添加多个多handler
Handler.setLevel(lel):指定被处理的信息级别,低于lel级别的信息将被忽略
Handler.setFormatter():给这个handler选择一个格式
Handler.addFilter(filt)、Handler.removeFilter(filt):新增或删除一个filter对象
每个Logger可以附加多个Handler。接下来我们就来介绍一些常用的Handler:
1) logging.StreamHandler
使用这个Handler可以向类似与sys.stdout或者sys.stderr的任何文件对象(file object)输出信息。它的构造函数是:
StreamHandler([strm])
其中strm参数是一个文件对象。默认是sys.stderr
2) logging.FileHandler
和StreamHandler类似,用于向一个文件输出日志信息。不过FileHandler会帮你打开这个文件。它的构造函数是:
FileHandler(filename[,mode])
filename是文件名,必须指定一个文件名。
mode是文件的打开方式。参见Python内置函数open()的用法。默认是’a',即添加到文件末尾。
3) logging.handlers.RotatingFileHandler
这个Handler类似于上面的FileHandler,但是它可以管理文件大小。当文件达到一定大小之后,它会自动将当前日志文件改名,然后创建 一个新的同名日志文件继续输出。比如日志文件是chat.log。当chat.log达到指定的大小之后,RotatingFileHandler自动把 文件改名为chat.log.1。不过,如果chat.log.1已经存在,会先把chat.log.1重命名为chat.log.2。。。最后重新创建 chat.log,继续输出日志信息。它的构造函数是:
RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]])
其中filename和mode两个参数和FileHandler一样。
maxBytes用于指定日志文件的最大文件大小。如果maxBytes为0,意味着日志文件可以无限大,这时上面描述的重命名过程就不会发生。
backupCount用于指定保留的备份文件的个数。比如,如果指定为2,当上面描述的重命名过程发生时,原有的chat.log.2并不会被更名,而是被删除。
4) logging.handlers.TimedRotatingFileHandler
这个Handler和RotatingFileHandler类似,不过,它没有通过判断文件大小来决定何时重新创建日志文件,而是间隔一定时间就 自动创建新的日志文件。重命名的过程与RotatingFileHandler类似,不过新的文件不是附加数字,而是当前时间。它的构造函数是:
TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]])
其中filename参数和backupCount参数和RotatingFileHandler具有相同的意义。
interval是时间间隔。
when参数是一个字符串。表示时间间隔的单位,不区分大小写。它有以下取值:
S 秒
M 分
H 小时
D 天
W 每星期(interval==0时代表星期一)
midnight 每天凌晨
import logging
#create logger
logger = logging.getLogger('TEST-LOG')
logger.setLevel(logging.DEBUG)
# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
# create file handler and set level to warning
fh = logging.FileHandler("access.log")
fh.setLevel(logging.WARNING)
# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# add formatter to ch and fh
ch.setFormatter(formatter)
fh.setFormatter(formatter)
# add ch and fh to logger
logger.addHandler(ch)
logger.addHandler(fh)
# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')
文件自动截断例子
复制代码
import logging
from logging import handlers
logger = logging.getLogger(__name__)
log_file = "timelog.log"
#fh = handlers.RotatingFileHandler(filename=log_file,maxBytes=10,backupCount=3)
fh = handlers.TimedRotatingFileHandler(filename=log_file,when="S",interval=5,backupCount=3)
formatter = logging.Formatter('%(asctime)s %(module)s:%(lineno)d %(message)s')
fh.setFormatter(formatter)
logger.addHandler(fh)
logger.warning("test1")
logger.warning("test12")
logger.warning("test13")
logger.warning("test14")
===================================================================================================
re模块(在Python程序里运行) linux里面的Python程序里执行
正则表达式的作用:匹配字符串
常用正则表达式符号
'.' 默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行
re.match('.','chen33333333331jkjkjkjkkkkkkkkkkkk')
re.match('.+','chen33333333331jkjkjkjkkkkkkkkkkkk')
re.match('^.','chen33333333331jkjkjkjkkkkkkkkkkkk')
re.match('^.\d','chen33333333331jkjkjkjkkkkkkkkkkkk')
re.match('^.+','chen33333333331jkjkjkjkkkkkkkkkkkk')
re.match('^.+\d','chen33333333331jkjkjkjkkkkkkkkkkkk')
'^' 匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE)
'$' 匹配字符结尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也可以
'*' 匹配*号前的字符0次或多次,re.findall("ab*","cabb3abcbbac") 结果为['abb', 'ab', 'a']
'+' 匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb']
'?' 匹配前一个字符1次或0次
'{m}' 匹配前一个字符m次
'{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb']
'|' 匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果'ABC'
'(...)' 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c
'\A' 只从字符开头匹配,re.search("\Aabc","alexabc") 是匹配不到的
'\Z' 匹配字符结尾,同$
'\d' 匹配数字0-9
'\D' 匹配非数字
'\w' 匹配[A-Za-z0-9]
'\W' 匹配非[A-Za-z0-9]
's' 匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 结果 '\t'
最常用的匹配语法
re.match 从头开始匹配(所以,^在match里面没有任何作用。match本身就是从开头开始匹配)
re.search 匹配包含,用的最多的。re.search('R.+a','chen2334Ronghua445555555')
re.findall 把所有匹配到的字符放到以列表中的元素返回
re.splitall 以匹配到的字符当做列表分隔符
re.sub 匹配字符并替换
反斜杠的困扰
与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\\\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r"\\"表示。同样,匹配一个数字的"\\d"可以写成r"\d"。有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
re.search("(abc){2}(\|\|=)(2)","alexabcabc||=||=") ---> abc||=||=
re.search("?P
re.search("?P
re.search("?P
re.search("?P
延伸:
a = re.search("?P
a['id']
--->'1234'
提取身份证信息:
'(?P
仅需轻轻知道的几个匹配模式
re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
例:re.search("[a-z]+","abcdA",flags=re.I)
M(MULTILINE): 多行模式,改变'^'和'$'的行为(参见上图)
例:re.search("[a-z]+","abcdA\ndksfisjfdlkline\nbird",flags=re.I)
S(DOTALL): 点任意匹配模式,改变'.'的行为
Python程序里:
import re
#re.match(模式,字符串)
re.match( "^chen", "chenkdjfisjdfjjjjjjjjjj123")
--->
<_sre.SRE_Match object;span=(0,4),match='chen'>
这里因为有返回,就是代表已经匹配到了,要是没有匹配到,就没有返回,也不报错。
判断是否匹配到:
res = re.match("^chen",'chenjjjjjjjjjj4344444')
print(res) 也可以
res.group()
--->
'chen' ---------> 这样也可以。
res = re.match('^chen\d','chen123444555jkkkkkkkkkkk')
res.group()
res = re.match('^chen\d+','chen123444555kkkkkkkkkkk')
res.group()
优先级:
1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14)) -(-4*3)/(16-3*2))