python 模块、包

模块

模块导入:

import导入模块干的事

1.产生新的名称空间
2.以新建的名称空间为全局名称空间,执行文件的代码
3.拿到一个模块名spam,指向spam.py产生的名称空间

from .. import ..

1.产生新的名称空间
2.以新建的名称空间为全局名称空间,执行文件的代码
3.直接拿到就是spam.py产生的名称空间中名字

优势:方便,不用加前缀
缺点:容易跟当前文件的名称空间冲突

__all__=['money']  #加入spam文件内[ ]内必须是字符串 
from spam import * #*表明all

模块搜索顺序

内存---->内置------->sys.pathnode

若倒入的模块跟执行的py不在一个路径下,则用sys.path:python

方法1.
#sys.path.insert更精准
import sys
#sys.path.append(r'/Users/boxfish-edu/PycharmProjects/untitled/d/a')
sys.path.insert(0,r'/Users/boxfish-edu/PycharmProjects/untitled/d/a')
import aaa
print(aaa.name)

方法2.
#a.b表示两层目录
from a.b import bbb
print(bbb.name)

正则表达式re模块

经常使用正则表达式符号

'.'     默认匹配除\n以外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行
'^'     匹配字符开头,若指定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'
 
'(?P<name>...)' 分组匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city") 结果{'province': '3714', 'city': '81', 'birthday': '1993'}

经常使用的匹配语法

re.match 从头开始匹配
re.search 匹配包含
re.findall 把全部匹配到的字符放到以列表中的元素返回
re.splitall 以匹配到的字符当作列表分隔符
re.sub      匹配字符并替换
print(re.findall('a.c','abc1\nn2a\nc3\tad_efa * | - =',re.S)) #加上re.s可使.匹配\n

print(re.findall('al(?:e)x\smak(?:e)','alex make love'))   #固定语法 不仅仅匹配括号里的

正则表达式概念

  1. 使用单个字符串来描述匹配一系列符合某个句法规则的字符串
  2. 是对字符串操做的一种逻辑公式
  3. 应用场景:处理文本和数据
  4. 正则表示是过程:依次拿出表达式和文本中的字符比较,若是每个字符都能匹配,则匹配成功;不然匹配失败

字符匹配

字符 描述
. 匹配任意一个字符(除了\n)
\d \D 数字/非数字
\s \S 空白/非空白字符
\w \W 单词字符[a-zA-Z0-9]/非单词字符
\b \B 单词边界,一个\w与\W之间的范围,顺序可逆/非单词边界
  • 匹配任意一个字符
# 匹配字符串abc,.表明b
 >>> re.match('a.c','abc').group()
'abc'
  • 数字与非数字
# 匹配任意一数字
 >>> re.match('\d','1').group()
'1'
 # 匹配任意一个非数字
 >>> re.match('\D','a').group()
'a'
  • 空白与非空白字符
# 匹配任意一个空白字符
 >>> re.match("\s"," ").group()
' '
 # 匹配任意一个非空白字符
 >>> re.match("\S","1").group()
'1'
 >>> re.match("\S","a").group()
'a'
  • 单词字符与非单词字符

单词字符即表明[a-zA-Z0-9]mysql

# 匹配任意一个单词字符
 >>> re.match("\w","a").group()
'a'
 >>> re.match("\w","1").group()
'1'
 # 匹配任意一个非单词字符
 >>> re.match("\W"," ").group()
' '

次数匹配

字符 匹配
* 匹配前一个字符0次或者无限次
+ 匹配前一个字符1次或者无限次
? 匹配前一个字符0次或者1次
{m}/{m,n} 匹配前一个字符m次或者N次
*?/+?/?? 匹配模式变为贪婪模式(尽量少匹配字符)
  • 介绍
字符 匹配
prev? 0个或1个prev
prev* 0个或多个prev,尽量多地匹配
prev*? 0个或多个prev,尽量少地匹配
prev+ 1个或多个prev,尽量多地匹配
prev+? 1个或多个prev,尽量少地匹配
prev{m} m个连续的prev
prev{m,n} m到n个连续的prev,尽量多地匹配
prev{m,n}? m到n个连续的prev,尽量少地匹配
[abc] a或b或c
[^abc] 非(a或b或c)
  • 匹配前一个字符0次或者无限次
>>> re.match('[A-Z][a-z]*','Aaa').group()
'Aaa'
 >>> re.match('[A-Z][a-z]*','Aa').group()
'Aa'
 >>> re.match('[A-Z][a-z]*','A').group()
'A'
  • 匹配前一个字符1次或者无限次
# 匹配前一个字符至少一次,若是一次都没有就会报错
 >>> re.match('[A-Z][a-z]+','A').group()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
>>> re.match('[A-Z][a-z]+','Aa').group()
'Aa'
 >>> re.match('[A-Z][a-z]+','Aaaaaaa').group()
'Aaaaaaa'
  • 匹配前一个字符0次或者1次
>>> re.match('[A-Z][a-z]?','A').group()
'A'
 # 只匹配出一个a
 >>> re.match('[A-Z][a-z]?','Aaaa').group()
'Aa'
  • 匹配前一个字符m次或者N次
#匹配前一个字符至少5次
 >>> re.match('\w{5}','asd234').group()
'asd23'
 # 匹配前面的字符6-10次
 >>> re.match('\w{6,10}','asd234').group()
'asd234'
 # 超过的字符就匹配不出来
 >>> re.match('\w{6,10}','asd2313qeadsd4').group()
'asd2313qea'
  • 匹配模式变为贪婪模式
>>> re.match(r'[0-9][a-z]*','1bc').group()
'1bc'
 # *?匹配0次或者屡次
 >>> re.match(r'[0-9][a-z]*?','1bc').group()
'1'
 # +?匹配一次或者屡次,可是只匹配了一次
 >>> re.match(r'[0-9][a-z]+?','1bc').group()
'1b'
 # ??匹配0次或者一次
 >>> re.match(r'[0-9][a-z]??','1bc').group()
'1'

贪婪匹配和非贪婪匹配web

边界匹配

字符 匹配
^ 匹配字符串开头
$ 匹配字符串结尾
\A \Z 指定的字符串必须出如今开头/结尾
  • 匹配字符串开头
# 必须以指定的字符串开头,结尾必须是@163.com
 >>> re.match('^[\w]{4,6}@163.com$','asdasd@163.com').group()
'asdasd@163.com'
  • 匹配字符串结尾
# 必须以.me结尾
 >>> re.match('[\w]{1,20}.me$','ansheng.me').group()
'ansheng.me'
  • 指定的字符串必须出如今开头/结尾
>>> re.match(r'\Awww[\w]*\me','wwwanshengme').group()
'wwwanshengme'

正则表达式分组匹配

  • | 匹配左右任意一个表达式
>>> re.match("www|me","www").group()
'www'
 >>> re.match("www|me","me").group()
'me'
  • (ab) 括号中表达式做为一个分组
# 匹配163或者126的邮箱
 >>> re.match(r'[\w]{4,6}@(163|126).com','asdasd@163.com').group()
'asdasd@163.com'
 >>> re.match(r'[\w]{4,6}@(163|126).com','asdasd@126.com').group()
'asdasd@126.com'
  • (?P ) 分组起一个别名
>>> re.search("(?P<zimu>abc)(?P<shuzi>123)","abc123").groups()
('abc', '123')
  • 引用别名为name的分组匹配字符串
>>> res.group("shuzi")
'123'
 >>> res.group("zimu")
'abc'

re模块经常使用的方法

  • re.match()

语法格式:正则表达式

match(pattern, string, flags=0)

释意:算法

Try to apply the pattern at the start of the string, returning a match object, or None if no match was found.sql

实例:shell

# 从头开始匹配,匹配成功则返回匹配的对象
 >>> re.match("abc","abc123def").group()
'abc'
 # 从头开始匹配,若是没有匹配到对应的字符串就报错
 >>> re.match("\d","abc123def").group()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
  • re.search()

语法格式:编程

search(pattern, string, flags=0)

释意:

Scan through string looking for a match to the pattern, returning a match object, or None if no match was found.

实例:

# 匹配整个字符串,匹配到第一个的时候就返回匹配到的对象
 >>> re.search("\d","abc1123def").group()
'1'
  • re.findall()

语法格式:

findall(pattern, string, flags=0)

释意:

Return a list of all non-overlapping matches in the string.

实例:

# 匹配字符串全部的内容,把匹配到的字符串以列表的形式返回
 >>> re.findall("\d","abc123def456")
['1', '2', '3', '4', '5', '6']
  • re.split

语法格式:

split(pattern, string, maxsplit=0)

释意:

Split the source string by the occurrences of the pattern, returning a list containing the resulting substrings.

实例:

# 指定以数字进行分割,返回的是一个列表对象
 >>> re.split("\d+","abc123def4+-*/56")
['abc', 'def', '+-*/', '']
 # 以多个字符进行分割
 >>> re.split("[\d,]","a,b1c")
['a', 'b', 'c']
  • re.sub()

语法格式:

sub(pattern, repl, string, count=0)

释意:

Return the string obtained by replacing the leftmost non-overlapping occurrences of the pattern in string by the replacement repl. repl can be either a string or a callable;
if a string, backslash escapes in it are processed. If it is a callable, it's passed the match object and must return a replacement string to be used.

实例:

# 把abc替换成def
 >>> re.sub("abc","def","abc123abc")
'def123def'
 # 只替换查找到的第一个字符串
 >>> re.sub("abc","def","abc123abc",count=1)
'def123abc'

实例

string方法包含了一百个可打印的ASCII字符,大小写字母、数字、空格以及标点符号

>>> import string
 >>> printable = string.printable
 >>> printable
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
>>> import re
 # 定义的字符串
 >>> source = '''I wish I may, I wish I migth
... Hava a dish of fish tonight.'''
 # 在字符串中检索wish
 >>> re.findall('wish',source)
['wish', 'wish']
 # 对源字符串任意位置查询wish或者fish
 >>> re.findall('wish|fish',source)
['wish', 'wish', 'fish']
 # 从字符串开头开始匹配wish
 >>> re.findall('^wish',source)    
[]
 # 从字符串开头匹配I wish
 >>> re.findall('^I wish',source)
['I wish']
 # 从字符串结尾匹配fish
 >>> re.findall('fish$',source)   
[]
 # 从字符串结尾匹配fish tonight.
 >>> re.findall('fish tonight.$',source)
['fish tonight.']
 # 查询以w或f开头,后面紧跟着ish的匹配
 >>> re.findall('[wf]ish',source)
['wish', 'wish', 'fish']
 # 查询以若干个w\s\h组合的匹配
 >>> re.findall('[wsh]+',source) 
['w', 'sh', 'w', 'sh', 'h', 'sh', 'sh', 'h']
 # 查询以ght开头,后面紧跟着一个非数字和字母的匹配
 >>> re.findall('ght\W',source)
['ght.']
 # 查询已以I开头,后面紧跟着wish的匹配
 >>> re.findall('I (?=wish)',source)
['I ', 'I ']
 # 最后查询以wish结尾,前面为I的匹配(I出现次数尽可能少)
 >>> re.findall('(?<=I) wish',source)
[' wish', ' wish']
  • 匹配时不区分大小写
>>> re.match('a','Abc',re.I).group()
'A'
  • r 源字符串,转义,若是要转义要加两个\n
>>> import re
 >>> pa = re.compile(r'ansheng')
 >>> pa.match("ansheng.me")
<_sre.SRE_Match object; span=(0, 7), match='ansheng'>
 >>> ma = pa.match("ansheng.me")
 >>> ma
<_sre.SRE_Match object; span=(0, 7), match='ansheng'>
 # 匹配到的值存到group内
 >>> ma.group()
'ansheng'
 # 返回字符串的全部位置
 >>> ma.span()
(0, 7)
 # 匹配的字符串会被放到string中
 >>> ma.string
'ansheng.me'
 # 实例放在re中
 >>> ma.re
re.compile('ansheng')

time模块

import time

#时间戳
print(time.time())

#结构化的时间(struct_time):struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时)
print(time.localtime())     #本地时区的struct_time
print(time.localtime().tm_year)
print(time.gmtime())      #UTC时区的struct_time

#格式化字符串
print(time.strftime('%Y-%m-%d %H:%M:%S'))
print(time.strftime('%Y-%m-%d %X'))

print(time.localtime(123123131))   #将一个时间戳转换为当前时区的struct_time

print(time.localtime(time.time()))      #时间戳->结构化时间
print(time.mktime(time.localtime()))    #将一个struct_time转化为时间戳。

print(time.strftime('%Y %X',time.localtime()))  #结构化时间->格式化字符串时间
print(time.strptime('2017-06-19 10:41:28','%Y-%m-%d %X'))  #格式化字符串时间->结构化时间

print(time.ctime(123123132))
print(time.asctime(time.localtime()))

random 模块

import random
print(random.random())  # (0,1)----float    大于0且小于1之间的小数

print(random.randint(1, 3))  # [1,3]  大于等于1且小于等于3之间的整数

print(random.randrange(1, 3))  # [1,3)  大于等于1且小于3之间的整数
print(random.randrange(1, 10,2))

print(random.choice([1, '23', [4, 5]]))  # 1或者23或者[4,5]

print(random.sample([1, '23', [4, 5]], 2))  # 列表元素任意2个组合

print(random.uniform(1, 3))  # 大于1小于3的小数,如1.927109612082716

item = [1, 3, 5, 7, 9]
random.shuffle(item)  # 打乱item的顺序,至关于"洗牌"
print(item)

随机选择IP

proxy_ip=[
    '1.1.1.1',
    '1.1.1.2',
    '1.1.1.3',
    '1.1.1.4',
]
print(random.choice(proxy_ip))

生成验证码

def v_code(n=5):
    res= ''
    for i in range(n):
        a = random.randint(0,9)
        b = chr(random.randint(65,90))
        c = random.choice([a,b])
        res +=str(c)
    return res

a = v_code(5)
print(a)

os模块

os模块是与操做系统交互的一个接口

os.getcwd() 获取当前工做目录,即当前python脚本工做的目录路径
os.chdir("dirname")  改变当前脚本工做目录;至关于shell下cd
os.curdir  返回当前目录: ('.')
os.pardir  获取当前目录的父目录字符串名:('..')
os.makedirs('dirname1/dirname2')    可生成多层递归目录
os.removedirs('dirname1')    若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname')    生成单级目录;至关于shell中mkdir dirname
os.rmdir('dirname')    删除单级空目录,若目录不为空则没法删除,报错;至关于shell中rmdir dirname
os.listdir('dirname')    列出指定目录下的全部文件和子目录,包括隐藏文件,并以列表方式打印
os.remove()  删除一个文件
os.rename("oldname","newname")  重命名文件/目录
os.stat('path/filename')  获取文件/目录信息
os.sep    输出操做系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep    输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep    输出用于分割文件路径的字符串 win下为;,Linux下为:
os.name    输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command")  运行shell命令,直接显示
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.getsize(path) 返回path的大小
在Linux和Mac平台上,该函数会原样返回path,在windows平台上会将路径中全部字符转换为小写,并将全部斜杠转换为饭斜杠。
>>> os.path.normcase('c:/windows\\system32\\')   
'c:\\windows\\system32\\'   
   

规范化路径,如..和/
>>> os.path.normpath('c://windows\\System32\\../Temp/')   
'c:\\windows\\Temp'   

>>> a='/Users/jieli/test1/\\\a1/\\\\aa.py/../..'
>>> print(os.path.normpath(a))
/Users/jieli/test1
os路径处理
#方式一:推荐使用
import os
#具体应用
import os,sys
possible_topdir = os.path.normpath(os.path.join(
    os.path.abspath(__file__),
    os.pardir, #上一级
    os.pardir,
    os.pardir
))
sys.path.insert(0,possible_topdir)


#方式二:不推荐使用
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

sys模块

sys.argv           命令行参数List,第一个元素是程序自己路径
sys.exit(n)        退出程序,正常退出时exit(0)
sys.version        获取Python解释程序的版本信息
sys.maxint         最大的Int值
sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform       返回操做系统平台名称


进度条:
import sys,time
for i in range(50):
    sys.stdout.write('%s\r' %('#'*i))   #\r将光标移动到首行
    sys.stdout.flush()
    time.sleep(0.1)

'''
注意:在pycharm中执行无效,请到命令行中以脚本的方式执行
'''

shutil模块

高级的 文件、文件夹、压缩包 处理模块

将文件内容拷贝到另外一个文件中

import shutil
shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))

拷贝文件

shutil.copyfile('f1.log', 'f2.log') #目标文件无需存在

仅拷贝权限。内容、组、用户均不变

shutil.copymode('f1.log', 'f2.log') #目标文件必须存在

仅拷贝状态的信息,包括:mode bits, atime, mtime, flags

shutil.copystat('f1.log', 'f2.log') #目标文件必须存在

拷贝文件和权限

import shutil
shutil.copy('f1.log', 'f2.log')

拷贝文件和状态信息

import shutil
shutil.copy2('f1.log', 'f2.log')

shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,详细:

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(path='.')
z.close()

zipfile压缩解压缩
import tarfile

# 压缩
>>> t=tarfile.open('/tmp/egon.tar','w')
>>> t.add('/test1/a.py',arcname='a.bak')
>>> t.add('/test1/b.py',arcname='b.bak')
>>> t.close()


# 解压
>>> t=tarfile.open('/tmp/egon.tar','r')
>>> t.extractall('/egon')
>>> t.close()

tarfile压缩解压缩

json 模块

import json
#序列化的过程:dic--->res=json.dups(dic)--->f.write(res)
dic={
    'name':'alex',
    'age':9000,
    'height':'150cm',
}
with open('a.json','w') as f:
    res = json.dumps(dic)
    print(res, type(res))
    f.write(res)

#反序列化的过程:dic =f.read()---> res = json.loads(res)--->dic=res
with open('a.json','r') as f:
    res = f.read()
    dic = json.loads(res)
    print(dic,type(dic))
    print(dic['name'])

#json的便捷操做
json.dump(dic,open('b.json','w'))

res = json.load(open('b.json','r'))
print(res)

pickle 模块

import pickle
dic={'name':'alex','age':13}
print(pickle.dumps(dic))
with open('a.pkl','wb') as f:
    f.write(pickle.dumps(dic))

with open('a.pkl','rb') as f:
    d = pickle.loads(f.read())
    print(d,type(d))

pickle.dump(dic,open('b.pkl','wb'))
res = pickle.load(open('b.pkl','rb'))
print(res)

import json
import pickle
def func():
    print('from func')

#json.dumps(func)# 报错,json不支持python的函数类型
f=pickle.dumps(func)
print(f)

pickle.dump(func,open('c.pkl','wb'))
res=pickle.load(open('c.pkl','rb'))
print(res)
res()

Pickle的问题和全部其余编程语言特有的序列化问题同样,就是它只能用于Python,而且可能不一样版本的Python彼此都不兼容,所以,只能用Pickle保存那些不重要的数据,不能成功地反序列化也不要紧。


shelve模块

shelve模块比pickle模块简单,只有一个open函数,返回相似字典的对象,可读可写;key必须为字符串,而值能够是python所支持的数据类型

import shelve
f=shelve.open(r'sheve.txt')
f['student1']={'name':'egon','age':18,'height':'180cm'}
print(f['student1']['name'])
f.close()

xml模块

笔记

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>

xml数据

xml操做:

#!/usr/bin/python
# -*- coding:utf-8 -*-

import xml.etree.ElementTree as ET

tree = ET.parse("a")
root = tree.getroot()

print(root.iter('year'))        #全文搜索
print(root.find('country'))     #在root的子节点找,只找一个
print(root.findall('country'))  #在root的子节点找,找全部


for country in root:
    print('=====>',country.attrib['name'])
    for item in country:
        print(item.tag,item.text,item.attrib)

for year in root.iter('year'):
    print(year.tag,year.text,year.attrib)   #tag,text,attrib 分别描述不一样的内容


#修改
for year in root.iter('year'):
    print(year.text)
    year.text=str(int(year.text)+1)
    print(year.attrib)
    year.set('update','yes')


tree.write('b.xml')     #建立并修改文件
tree.write('a')         #更改当前文件


for country in root:
    print(country)
    print('===>',country.find('year'))
    year=country.find('year')
    if int(year.text) > 2010:
        country.remove(year)

tree.write('d.xml')


#增长
for country in root:
    print(country)
    # print('===>',country.find('year'))
    year=country.find('year')
    if int(year.text) > 2010:
        year2 = ET.Element('year2')
        year2.text=str(int(year.text)+1)
        year2.set('update','yes')
        country.append(year2)
tree.write('e.xml')


#本身建立xml文档:
new_xml = ET.Element("namelist")
name = ET.SubElement(new_xml, "name", attrib={"enrolled": "yes"})
age = ET.SubElement(name, "age", attrib={"checked": "no"})
sex = ET.SubElement(name, "sex")
sex.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)

ET.dump(new_xml)  # 打印生成的格式

参考

Python标准库系列之xml模块

Python’s interfaces for processing XML are grouped in the xml package.

带分隔符的文件仅有两维的数据:行和列。若是你想在程序之间交换数据结构,须要一种方法把层次结构、序列、集合和其余的结构编码成文本。

XML是最突出的处理这种转换的标记(markup)格式,它使用标签(tag)分个数据,以下面的实例文件menu.xml所示:

<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>安生&#39;s Blog</title>
  <subtitle>大好时光!</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="https://blog.ansheng.me/"/>
  <updated>2016-05-24T15:29:19.000Z</updated>
  <id>https://blog.ansheng.me/</id>
  
  <author>
    <name>安生</name>
  </author>
</feed>

XML的一些重要特性

  1. 标签以一个<字符开头,例如实例中的feed、title、subtitle、author。
  2. 忽略空格
  3. 一般一个开始标签跟一段其余的内容,而后是最后相匹配的结束标签,例如 大好时光!
  4. 标签之间是能够存在多级嵌套的
  5. 可选属性(attribute)能够出如今开始标签里
  6. 标签中能够包含值(value)
  7. 若是一个命名为thing的标签内没有内容或者子标签,那么它能够用在右尖括号的前面添加斜杠的简单标签所表示,例如 代替开始和结束都存在的标签。
  8. 存放数据的位置能够是任意的---属性、值或者子标签。

XML一般用于数据传送和消息,它存在一些子格式,如RSS和Atom,例如:https://blog.ansheng.me/atom.xml

在Python中解析XML最简单的方法是使用ElementTree

模块 说明
xml.etree.ElementTree the ElementTree API, a simple and lightweight XML processor

建立xml文件

导入ElementTree方法,起一个别名为ET

>>> from xml.etree import ElementTree as ET

建立顶级标签

>>> level_1 = ET.Element("famliy")

建立二级标签,tag名name,attrib标签属性

>>> level_2 = ET.SubElement(level_1, "name", attrib={"enrolled":"yes"})

建立三级标签

>>> level_3 = ET.SubElement(level_2, "age", attrib={"checked":"no"})

生成文档

>>> tree = ET.ElementTree(level_1)

写入文件中

>>> tree.write('oooo.xml',encoding='utf-8', short_empty_elements=False)

导入os模块,用os模块中的system方法执行shell命令查看刚才建立的oooo.xml文件

>>> import os
>>> os.system("cat oooo.xml")
# 生成出来的文档是没有换行的
<famliy><name enrolled="yes"><age checked="no"></age></name></famliy>0

把刚才生成的文件下载到本地,而后用浏览器打开就能够看到分级层次了。

建立一个有换行的XML文件

代码

from xml.etree import ElementTree as ET
from xml.dom import minidom

root = ET.Element('level1',{"age":"1"})
son = ET.SubElement(root,"level2",{"age":"2"})
ET.SubElement(son, "level3", {"age":"3"})

# tree = ET.ElementTree(root)
# tree.write("abc.xml", encoding="utf-8",xml_declaration=True,short_empty_elements=False)

def prettify(root):
    rough_string = ET.tostring(root, 'utf-8')
    reparsed = minidom.parseString(rough_string)
    return reparsed.toprettyxml(indent="\t")

new_str = prettify(root)
f = open("new_out.xml", "w")
f.write(new_str)
f.close()

生成的xml文件

<?xml version="1.0" ?>
<level1 age="1">
    <level2 age="2">
        <level3 age="3"/>
    </level2>
</level1>

解析XML

first.xml文件内容为:

<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year age="19">2025</year>
        <gdppc>141100</gdppc>
        <neighbor direction="E" name="Austria" />
        <neighbor direction="W" name="Switzerland" />
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year age="19">2028</year>
        <gdppc>59900</gdppc>
        <neighbor direction="N" name="Malaysia" />
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year age="19">2028</year>
        <gdppc>13600</gdppc>
        <neighbor direction="W" name="Costa Rica" />
        <neighbor direction="E" name="Colombia" />
    </country>
</data>

first.xml文件在/root目录下

利用ElementTree.XML将字符串解析成xml对象

>>> from xml.etree import ElementTree as ET
# 打开文件,读取XML内容,将字符串解析成xml特殊对象,root代指xml文件的根节点 
>>> root = ET.XML(open('first.xml', 'r').read())
>>> root.tag
'data'
>>> for node in root:
...  print(node.tag, node.attrib)
... 
('country', {'name': 'Liechtenstein'})
('country', {'name': 'Singapore'})
('country', {'name': 'Panama'})
>>> print(node.find('rank').text)
69

利用ElementTree.parse将文件直接解析成xml对象

>>> from xml.etree import ElementTree as ET
# 直接解析xml文件
>>> tree = ET.parse("first.xml")
# 获取xml文件的根节点
>>> root = tree.getroot()
>>> root.tag
'data'

遍历XML中指定的节点

>>> from xml.etree import ElementTree as ET
>>> tree = ET.parse("first.xml")
>>> root = tree.getroot()
>>> for node in root.iter('year'):
        # 输出node的tag和内容
...     print(node.tag, node.text)
...
year 2025
year 2028
year 2028

增、删、改XML

为节点添加属性

>>> from xml.etree import ElementTree as ET
>>> tree = ET.parse("first.xml")
>>> root = tree.getroot()
>>> for node in root.iter("year"):
        # 查看原来的属性
...     print(node.attrib)
...
{}
{}
{}
>>> for node in root.iter("year"):
       # 添加属性
...    node.set("OS","Linux")
...
>>> for node in root.iter("year"):
        # 查看添加的属性
...     print(node.attrib) 
...
{'OS': 'Linux'}
{'OS': 'Linux'}
{'OS': 'Linux'}
# 把内容写入文件
>>> tree.write("first.xml")

删除节点属性

>>> from xml.etree import ElementTree as ET
>>> tree = ET.parse("first.xml")
>>> root = tree.getroot()
>>> for node in root.iter("year"):
        # 删除节点的OS属性
...     del node.attrib['OS']
...
# 写入到文件当中
>>> tree.write("first.xml")

查看属性

>>> from xml.etree import ElementTree as ET
>>> tree = ET.parse("first.xml")
>>> root = tree.getroot()
>>> for node in root.iter("year"):
...  print(node.attrib)
...
# 节点内容为空
{}
{}
{}

修改节点内容

修改year内的数字自加1

>>> from xml.etree import ElementTree as ET
>>> tree = ET.parse("first.xml")
>>> root = tree.getroot() 
>>> for node in root.iter("year"):
        # 输出原来year的内容
...     print(node.text)
        # 原来的值自加+
...     new_year = int(node.text) + 1
...     node.text = str(new_year)
...
2025
2028
2028 
# 写入文件中
>>> tree.write("first.xml")
>>> for node in root.iter("year"):
        # 输出写入文件以后year的内容
...     print(node.text)
...
2026
2029
2029

对节点操做的方法

获取节点的方法

>>> from xml.etree import ElementTree as ET
>>> tree = ET.parse("first.xml")
>>> root = tree.getroot()
>>> print(dir(root))
['__class__', '__copy__', '__deepcopy__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'extend', 'find', 'findall', 'findtext', 'get', 'getchildren', 'getiterator', 'insert', 'items', 'iter', 'iterfind', 'itertext', 'keys', 'makeelement', 'remove', 'set']

方法有这么多,那么咱们经常使用的也就是下面的几个

方法名 说明
tag 获取tag标签名
attrib 获取节点的属性
find 获取节点的内容
iter 进行迭代
set 设置属性
get 获取属性

实例

判断QQ是否在线

腾讯提供了可以查看QQ号码是否在线的API,Y=在线;N=离线;E=QQ号码错误;A=商业用户验证失败;V=免费用户超过数量

>>> import requests
>>> from xml.etree import ElementTree as ET
>>> r = requests.get("http://www.webxml.com.cn//webservices/qqOnlineWebService.asmx/qqCheckOnline?qqCode=6087414")
>>> result = r.text
>>> from xml.etree import ElementTree as ET
>>> node = ET.XML(result)
>>> if node.text == "Y":
...    print("在线")
... else:
...    print("离线")
...
在线

获取列车起止时间

代码

r = requests.get("http://www.webxml.com.cn/WebServices/TrainTimeWebService.asmx/getDetailInfoByTrainCode?TrainCode=K234&UserID=")
result = r.text
root = ET.XML(result)
for node in root.iter('TrainDetailInfo'):
    print(node.find('TrainStation').text,node.find('ArriveTime').text,node.find("StartTime").text)

执行结果

C:\Python35\python.exe F:/Python_code/sublime/Week5/Day01/xml_mod.py
上海(车次:K234\K235) None 11:12:00
# 地点 中止    启动
昆山 11:45:00 11:48:00
苏州 12:12:00 12:16:00
无锡 12:44:00 12:55:00
常州 13:22:00 13:26:00
镇江 14:13:00 14:16:00
南京 15:04:00 15:16:00
蚌埠 17:27:00 17:50:00
徐州 19:38:00 19:58:00
商丘 22:12:00 22:17:00
开封 23:49:00 23:53:00
郑州 00:37:00 01:14:00
新乡 02:20:00 02:22:00
鹤壁 03:01:00 03:03:00
安阳 03:33:00 03:36:00
邯郸 04:11:00 04:16:00
邢台 04:47:00 04:51:00
石家庄 06:05:00 None

Process finished with exit code 0

hashlib 模块

This module implements a common interface to many different secure hash and message digest algorithms. Included are the FIPS secure hash algorithms SHA1, SHA224, SHA256, SHA384, and SHA512 (defined in FIPS 180-2) as well as RSA’s MD5 algorithm (defined in Internet RFC 1321). The terms “secure hash” and “message digest” are interchangeable. Older algorithms were called message digests. The modern term is secure hash.

官方文档:https://docs.python.org/3.5/library/hashlib.html

用于加密相关的操做,代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

md5加密

>>> import hashlib
m = hashlib.md5()
m.update('me'.encode('utf-8'))
print(m.hexdigest())

m = hashlib.md5()
with open('a','rb') as f:
    for i in f:
        m.update(i)
    md5_num = m.hexdigest()
print(md5_num)

sha1

>>> import hashlib
>>> hash = hashlib.sha1()
>>> hash.update(bytes('ansheng', encoding='utf-8'))
>>> hash.hexdigest()
'd1dec3927fbe94ace7f7ebe6c53a844e0265455a'

sha256

import hashlib
s = hashlib.sha256()
s.update('helloword'.encode('utf-8'))
print(s.hexdigest())

sha384

>>> import hashlib
>>> hash = hashlib.sha384()
>>> hash.update(bytes('ansheng', encoding='utf-8'))
>>> hash.hexdigest()
'01cab50e3cc7801fec2988573ad62a645daf636a6d2a47d41c7a456113bee6e657a3ff367029f617e38a03d732c8113d'

sha512

>>> import hashlib
>>> hash = hashlib.sha512()
>>> hash.update(bytes('ansheng', encoding='utf-8'))
>>> hash.hexdigest()
'79cc48a191152112bd8285979784fc4bba9b0f2d5ac26f96de1ec87a6fbf4935dcb3ba9bc027c3791875b96dd725e01863602f59d4a561bbd2823495cd4553fc'

撞库实例:

import hashlib
passwds=[
    'alex3714',
    'alex1313',
    'alex94139413',
    'alex123456',
    '123456alex',
    'a123lex',
    ]

def make_pass_dic(passwords):
    dic = {}
    m = hashlib.md5()
    for passwd in passwds:
        m.update(passwd.encode('utf-8'))
        dic[passwd] = m.hexdigest()
    return dic


def break_code(cryptograph,dic_passwd):
    for k,v in dic_passwd.items():
        if v == cryptograph:
            print('密码是--->',k)


cryptograph = 'aee949757a2e698417463d47acac93df'
break_code(cryptograph,make_pass_dic(passwds))

为防止别人对咱们的md5值进行撞库,咱们能够给md5加个盐

import hashlib
m=hashlib.md5('yihangbailushangqingtian'.encode('utf-8'))
m.update('alex3714'.encode('utf-8'))
print(m.hexdigest())

另一个加盐的模块

import hmac
h = hmac.new('egon123456'.encode('utf-8'))
h.update('alex3714'.encode('utf-8'))
print(h.hexdigest())

实例

根据用户输入的登陆名和口令模拟用户注册,计算更安全的MD5:
而后,根据修改后的MD5算法实现用户登陆的验证.

import hashlib
db = {}
def calc_md5(password):
    md5 = hashlib.md5()
    md5.update(password.encode())
    return md5.hexdigest()

def register(user,password):
    db[user] = calc_md5(password + user + 'the-Salt')

def login(user,password):
    p = calc_md5(password + user + 'the-Salt')
    if user in db:
        if db[user] == p:
            print('login successful')
        else:
            print('wrong')
    else:
        print('can not find',username)

while True:
    x = input('register:1 login:2 quit:0\n')
    if x == '0':
        break
    elif x == '1':
        user = input('input your name:\n')
        password = input('input your password:\n')
        register(user, password)

    elif x == '2':
        user = input('input your name:\n')
        password = input('input your password:\n')
        login(user, password)
    else:
        print('wrong')

subprocess 模块

import subprocess
res = subprocess.Popen('ls',shell=True,stdout=subprocess.PIPE)
print(res)
print(res.stdout.read().decode('gbk'))


#stderr 能够在出错是不报错
res = subprocess.Popen('diasd',shell=True,
                       stderr = subprocess.PIPE,
                       stdout = subprocess.PIPE
                       )

print('---->',res.stdout.read())
print('---->',res.stderr.read().decode('gbk'))


res1 = subprocess.Popen(r'ls /Users/boxfish-edu/PycharmProjects/untitled/e',shell=True,stdout=subprocess.PIPE)
#print(res1.stdout.read())
res=subprocess.Popen(r'ls test*',shell=True,
                     stdin=res1.stdout,
                     stderr=subprocess.PIPE,
                     stdout=subprocess.PIPE)

print('===>',res.stdout.read().decode('gbk'))#管道取一次就空了
print('===>',res.stdout.read().decode('gbk'))#管道取一次就空了

官网介绍:

This module allows you to spawn processes, connect to their input/output/error pipes, and obtain their return codes.

经常使用方法实例

call()

执行命令,并返回状态码,状态码0表明命令执行成功,其余的都表示命令执行不成功

>>> ret = subprocess.call(["ls", "-l"], shell=False)
total 4
-rw-r--r-- 1 root root 172 May 25 21:21 file.conf
>>> ret
0

另外一种执行方式

# shell=True表示调用原生的shell命令去执行
>>> ret = subprocess.call("ls -l", shell=True)
total 4
-rw-r--r-- 1 root root 172 May 25 21:21 file.conf
>>> ret
0

check_call()

执行命令,若是执行状态码是0,则返回0,不然抛异常

# 执行一个正确的命令就会返回执行结果和状态码
>>> subprocess.check_call(["ls", "-l"])
total 4
-rw-r--r-- 1 root root 172 May 25 21:21 file.conf
0
# 若是执行的是一个错误的命令,那么就会返回错误信息
>>> subprocess.check_call(["ls", "a"])  
ls: cannot access a: No such file or directory
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.6/subprocess.py", line 505, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['ls', 'a']' returned non-zero exit status 2

check_output()

执行命令,若是状态码是0,则返回执行结果,不然抛异常

# 执行成功就把执行的结果赋值给变量V
>>> V = subprocess.check_output("python -V", shell=True)
# 执行错误的命令就会输出异常
>>> subprocess.check_output("pasas", shell=True)
'pasas' 不是内部或外部命令,也不是可运行的程序
或批处理文件。
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python35\lib\subprocess.py", line 629, in check_output
    **kwargs).stdout
  File "C:\Python35\lib\subprocess.py", line 711, in run
    output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command 'pasas' returned non-zero exit status 1

以上的三种执行方式在执行命令的时候,shell默认等于True,等于True的时候,括号内的命令是一行的,若是shell等于False,那么[]内的字符串就是命令的一个元素,执行的时候会把[]内的字符串拼接起来执行。

subprocess.Popen()

call()check_call()check_output()默认内部调用的都是subprocess.Popen(),而subprocess.Popen()则用于执行更复杂的系统命令。

参数

参数 说明
stdin 标准输入
stdout 标准输出
stderr 错误句柄
cwd 用于设置子进程的当前目录
env 用于指定子进程的环境变量。若是env = None,子进程的环境变量将从父进程中继承

执行普通命令

>>> subprocess.Popen("Python -V", shell=True)
<subprocess.Popen object at 0x0000025C97233C88>
# Python 3.5.1是输出出来的结果
>>> Python 3.5.1

执行命令分为两种:

  1. 输入便可获得输出,如:ifconfig
  2. 输入进行某交互式环境,依赖再输入,如:python
>>> import subprocess
# 先进入'/tmp'目录,而后在建立subprocess文件夹,shell=True无关紧要
>>> subprocess.Popen("mkdir subprocess", shell=True, cwd='/tmp',)
<subprocess.Popen object at 0x7f267cc3d390>
>>> import os
>>> os.system("ls /tmp")
subprocess

subprocess.Popen()实例

# 导入subprocess模块
import subprocess

# 执行python命令,进入python解释器,stdin标准输入、stdout标准输出、stderr错误输出,universal_newlines=True自动输入换行符
obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)

# 执行标准输入,write后面是输入的命令
obj.stdin.write("print(1)\n")
obj.stdin.write("print(2)")
# 输入以后关闭
obj.stdin.close()

# 读取标准输出的内容,赋值给cmd_out对象
cmd_out = obj.stdout.read()
# 关闭标准输出
obj.stdout.close()

# 读取错误输出的内容,赋值给cmd_error对象
cmd_error = obj.stderr.read()

# 关闭错误输出
obj.stderr.close()

# 输出内容
print(cmd_out)
print(cmd_error)

执行结果

C:\Python35\python.exe F:/Python_code/sublime/Week5/Day02/sub.py
1
2



Process finished with exit code 0
# 导入subprocess模块
import subprocess

# 执行python命令,进入python解释器,stdin标准输入、stdout标准输出、stderr错误输出,universal_newlines=True自动输入换行符
obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)

# 执行两条命令
obj.stdin.write("print(1)\n")
obj.stdin.write("print(2)")

# communicate把错误输出或者标准输出的内容赋值给out_error_list对象,若是有错误就赋值错误输出,不然就复制标准输出
out_error_list = obj.communicate()

# 输出out_error_list对象的内容
print(out_error_list)

执行结果

C:\Python35\python.exe F:/Python_code/sublime/Week5/Day02/sub.py
('1\n2\n', '')

Process finished with exit code 0
# 导入subprocess模块
import subprocess

# 执行python命令,进入python解释器,stdin标准输入、stdout标准输出、stderr错误输出,universal_newlines=True自动输入换行符
obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)


# 直接执行print("hello")命令,而后把错误或者正确的结果赋值给out_error_list对象
out_error_list = obj.communicate('print("hello")')

# 输出out_error_list对象的内容
print(out_error_list)

执行结果

C:\Python35\python.exe F:/Python_code/sublime/Week5/Day02/sub.py
('hello\n', '')

Process finished with exit code 0

logging日志模块

This module defines functions and classes which implement a flexible event logging system for applications and libraries.

The key benefit of having the logging API provided by a standard library module is that all Python modules can participate in logging, so your application log can include your own messages integrated with messages from third-party modules.

官方文档:https://docs.python.org/3.5/library/logging.html

logging模块用于便捷记录日志且线程安全。

日志级别

Level Numeric value
CRITICAL 50
ERROR 40
WARNING 30
INFO 20
DEBUG 10
NOTSET 0

只有大于当前日志等级的操做才会被记录。

写入单文件

代码

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
# 导入logging模块
import logging

# 建立一个log.log日志文件
logging.basicConfig(filename='log.log',
                    # 格式化的字符串
                    format='%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s',
                    # 时间
                    datefmt='%Y-%m-%d %H:%M:%S %p',
                    # 错误级别
                    level=logging.NOTSET
                    )

logging.critical('critical')
logging.error('error')
logging.warning('warning')
logging.info('info')
logging.debug('debug')
logging.log(logging.INFO, 'NOTSET')

执行结果

ansheng@ansheng-me:~$ ls 
log.py
ansheng@ansheng-me:~$ python log.py 
ansheng@ansheng-me:~$ ls
log.log  log.py
ansheng@ansheng-me:~$ cat log.log 
2016-05-27 21:46:15 PM - root - CRITICAL - log: critical
2016-05-27 21:46:15 PM - root - ERROR - log: error
2016-05-27 21:46:15 PM - root - WARNING - log: warning
2016-05-27 21:46:15 PM - root - INFO - log: info
2016-05-27 21:46:15 PM - root - DEBUG - log: debug
2016-05-27 21:46:15 PM - root - INFO - log: NOTSET

logging.basicConfig函数各参数

参数 说明
filename 指定日志文件名
filemode 和file函数意义相同,指定日志文件的打开模式,'w'或'a'
format 指定输出的格式和内容,format能够输出不少有用信息,以下所示
datefmt 指定时间格式,同time.strftime()
level 设置日志级别,默认为logging.WARNING

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 打印日志信息

多文件日志

对于上述记录日志的功能,只能将日志记录在单文件中,若是想要设置多个日志文件,logging.basicConfig将没法完成,须要自定义文件和日志操做对象。

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

import logging

# 建立文件
file_1 = logging.FileHandler("log1.log", "a")
# 建立写入的日志格式
fmt1 = logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s - %(module)s : %(message)s")
# 文件用格式
file_1.setFormatter(fmt1)

file_2 = logging.FileHandler("log2.log", "a")
fmt2 = logging.Formatter()
file_2.setFormatter(fmt2)

logger1 = logging.Logger("s1", level=logging.ERROR)
logger1.addHandler(file_1)
logger1.addHandler(file_2)

logger1.critical("1111")
# 定义文件
file_2_1 = logging.FileHandler('l2_1.log', 'a')
fmt = logging.Formatter()
file_2_1.setFormatter(fmt)

# 定义日志
logger2 = logging.Logger('s2', level=logging.INFO)
logger2.addHandler(file_2_1)

如上述建立的两个日志对象

  1. 当使用logger1写日志时,会将相应的内容写入 l1_1.log 和 l1_2.log 文件中
  2. 当使用logger2写日志时,会将相应的内容写入 l2_1.log 文件中

configparser模块

This module provides the ConfigParser class which implements a basic configuration language which provides a structure similar to what’s found in Microsoft Windows INI files. You can use this to write Python programs which can be customized by end users easily.

configparser用于处理特定格式的文件,其本质上是利用open来操做文件。

配置文件格式以下:

# 第一种注释方式
; 第二种注释方式
 
[node1]  # 节点
k1 = v1  # key = value
k2 : v2  # key : value

实例

import configparser

#为文件添加节点
config=configparser.ConfigParser()
config.read('a.ini',encoding='utf-8')

config.add_section('node1')
config.add_section('node2')
config.write(open('a.ini','w'))

#检查节点是否存在
print(config.has_section('node1'))      #存在返回True

#删除节点
config.remove_section('node2')
config.write(open('a.ini','w'))

#设置节点内的键值对
config.set('node1','name','ansheng')
config.set('node1', 'Blog_URL', "https://blog.ansheng.me")
config.set('node1', 'Hostname', "localhost.localhost")
config.set('node1', 'IP', "127.0.0.1")
config.write(open('a.ini', 'w'))

#检查节点内的key是否存在
#若是节点的Key存在就返回"True",不然返回"False"
print(config.has_option('node1', 'Name'))


#删除节点内的key

#若是删除的节点存在就返回"True",不然就返回"False"
print(config.remove_option('node1', 'IP'))


#获取指定节点下指定key的值
print(config.get('node1','name'))
#返回的字符串咱们能够设置成一下三种数据类型,分别是"int","float","bool"
v = config.getint('node1', 'name')
v = config.getfloat('node1', 'k1')
v = config.getboolean('node1', 'k1')

#获取指定节点下全部的key
#返回节点下面全部的Key列表
print(config.options('node1'))

#获取指定节点下全部的键值对
#返回一个列表,列表中每一个元组就是一个键值对
print(config.items('node1'))

#获取全部节点
#获取当前文件中有多少个节点
print(config.sections())

itertools 模块

datetime\traceback模块

json\pickle\xml\yaml\configparser 处理模




包的导入方式

执行文件都是test.py
1.
import glance.api.policy.get #报错,点的左边必须是包
import glance.api.policy
glance.api.policy.get()

2.
from glance.api import policy,versions
from glance.cmd import manage
from glance.db import models

policy.get()
manage.main()
models.register_models('mysql')
---
#注意与本文件内函数名之间的冲突
from glance.api.policy import get
from glance.api.versions import create_resource
from glance.cmd.manage import main
from glance.db.models import register_models
get()
create_resource('mysql')
main()
register_models('mysql')


3.
#前提在api下的__init__.py内加入__all__=['policy','versions']
from glance.api import *
policy.get()
print(policy)
print(versions)

4.
#前提在glance下的__init__py配置
from .api import *  #policy,versions
from .cmd import *  #mange
from .db import *   #models

#test.py
import glance
glance.policy.get()
glance.versions.create_resource('mysql')


备注:
import glance
print(glance)
直接倒入glace打印的是glace下的__init__.py

实例目录结构:
包能够是结构更清晰,便于开发者修改
'''
---glance
   |
   --api
        |
        ---__init__py
        ---policy.py
        ---versions.py
   --cmd
        |
        ---__init__.py
        ---manage.py
   --db
        |
        ---__init__.py
        ---models.py
   __init__.py
'''
相关文章
相关标签/搜索