目录
一、os模块
import os,time
'''获取当前脚本的工作目录'''
print(os.getcwd())
'''修改当前工作目录'''
os.chdir(r'D:\Projects\FirstPython')
print(os.getcwd())
'''返回当前目录'''
print(os.curdir)#.
'''返回父目录'''
print(os.pardir)#..
'''生成多层文件夹'''
os.makedirs('.\zzh\zhuzihan')#多次创建会报错
'''递归删除空文件夹'''
os.removedirs('zzh\zhuzihan')
'''生成单个文件夹'''
os.mkdir('zzh')
'''删除单级文件夹'''
os.rmdir('zzh')
'''列出指定文件夹下的所有文件目录以及子目录'''
print(os.listdir('.'))
'''删除一个文件'''
os.remove(r"testfiles\aaa1.txt")
'''重命名'''
os.rename(r"testfiles\aaa2.txt", r"testfiles\aaa.txt")
'''获取文件或者文件夹信息'''
print(os.stat(r"testfiles"))
print(os.stat(r"testfiles\aaa.txt"))
'''获取路径分隔符'''
print(os.sep)#windows下\,linux下/
'''输出当前平台下的终止符'''
print("++++++++",os.linesep,"------")#windows下是\r\n,linux下\n
'''输出用于分割文件路径的字符串'''
print(os.pathsep)
'''输出字符串指示大年使用平台'''
print(os.name)
'''运行shell命令,直接显示'''
os.system('dir')
''' 获取系统环境变量'''
print(os.environ)
'''返回path规范化的绝对路径'''
p = os.path.abspath(r'./testfiles')
print(p)
'''将path分割成目录和文件名二元组返回'''
print(os.path.split(p))
'''将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.join(path1[, path2[, ...]])
'''
print(os.path.join(os.path.dirname(p),os.path.basename(p)))
''' 返回path的目录。其实就是os.path.split(path)的第一个元素'''
print(os.path.dirname(p))
print(">>",os.path.dirname(r'testfiles'))
print(">>",os.path.dirname(r'./testfiles'))
'''返回path最后的文件名.如果path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素'''
print(os.path.basename(p))
print(">>",os.path.basename(r'testfiles'))
print(">>",os.path.basename(r'./testfiles'))
'''如果path存在,返回True;如果path不存在,返回False'''
print(os.path.exists(r'./testfiles'))
''' 如果path是一个存在的文件,返回True。否则返回False'''
print(os.path.isabs(r'./testfiles'))
'''如果path是一个存在的文件,返回True。否则返回False'''
print(os.path.isfile(r'./testfiles'))
'''如果path是一个存在的目录,则返回True。否则返回False'''
print(os.path.isdir(r'./testfiles'))
'''返回path所指向的文件或者目录的最后存取时间'''
print(os.path.getatime(r'./testfiles'))
'''返回path所指向的文件或者目录的最后修改时间'''
print(time.ctime(os.path.getmtime(r'./testfiles')))
二、sys模块
import sys
''' 退出程序,正常退出时exit(0)'''
sys.exit(0)
'''获取python解释器的版本信息'''
print(sys.version)
'''
按照模块的搜索路径顺序返回搜索路径,初始化时使用 PYTHONPATH环境变量的值
'''
print(sys.path)
print(sys.path.append("需要自己添加的模块路径"))
'''返回操作系统平台名称'''
print(sys.platform)
'''输入输出'''
sys.stdout.write('please:')
val = sys.stdin.readline()
print(type(val))#<class 'str'>
sys.stdout.write(val[:])
三、hashlib和hmac 加密模块
import hashlib
def encode_utf8(s):
return s.encode(encoding='utf-8')
'''
使用md5算法加密
'''
m = hashlib.md5()
print(m)
m.update("hello world".encode(encoding="utf-8"))
print(m.hexdigest())#十六进制方式5eb63bbbe01eeed093cb22bb8f5acdc3
m.update('alex'.encode(encoding="utf-8"))
print(m.hexdigest())#获取加密后的十六进制密文
m2 = hashlib.md5()
m2.update('hello worldalex'.encode(encoding="utf-8"))
print(m2.hexdigest())#获取加密后的十六进制密文
'''
sha256
'''
h = hashlib.sha256()
h.update("hello world".encode(encoding="utf-8"))
print(h.hexdigest())#获取加密后的十六进制密文
'''hex-based message authentication code 哈希消息认证码'''
import hmac
h = hmac.new(encode_utf8("key"),encode_utf8("message"),digestmod='MD5')
print(h.hexdigest())
h = hmac.new(key=encode_utf8("key"), digestmod='MD5')
h.update(encode_utf8("message"))
print(h.hexdigest())#获取加密后的十六进制密文
四、logging日志模块
import logging
'''
日志级别
默认的日志级别设置为WARNING
(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET),
默认的日志格式为日志级别:Logger名称:用户输出消息。
'''
logging.debug("debug message")
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
'''
可见在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有
filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
format:指定handler使用的日志显示格式。
datefmt:指定日期时间格式。
%a 周几 缩写
%Y %b(月 缩写) %d %H:%M:%S 年月日时分秒
level:设置rootlogger(后边会讲解具体概念)的日志级别
stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件(f=open('test.log','w')),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
format参数中可能用到的格式化串:
%(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用户输出的消息
filemod:文件模式,w输出到文件
'''
'''自定义日志格式'''
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
datefmt='%a, %d %b %Y %H:%M:%S',
filename=r'D:\Projects\FirstPython\day8\testfiles\test.log',
filemode='a')
logging.debug("debug message")
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical messageday')# #Wed, 19 Feb 2020 16:51:42 new4_logging模块.py[line:52] DEBUG debug message
'''
同时输出的文件和console
'''
logger = logging.getLogger('zhuzihan')
# 创建一个handler,用于写入日志文件
fh = logging.FileHandler(r'D:\Projects\FirstPython\day8\testfiles\test.log',encoding='utf-8')
# 再创建一个handler,用于输出到控制台
ch = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
logger.addHandler(fh) #logger对象可以添加多个fh和ch对象
logger.addHandler(ch)
logger.setLevel(logging.DEBUG)
logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')
五、configparser配置文件模块
import configparser
'''配置文件的生成'''
config = configparser.ConfigParser()
print(type(config))
config["DEFAULT"] = {"ServerAliveInterval":45,
"Compression":"yes",
"compressionLevel":'9'}
config['bitbucket.org'] = {}
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(r".\testfiles\config.conf",encoding='utf-8',mode='w') as conffile:
config.write(conffile)
'''配置文件的读取'''
config.read(r".\testfiles\config.conf",encoding='utf-8')
secs = config.sections()
defa = config.defaults()
print(config['topsecret.server.com']['Host Port'])
for kv in config['topsecret.server.com']:#打印别的内容的时候,default下的配置项也会在这里面
print(kv)
'''删除配置文件一节'''
if 'topsecret.server.com' in secs:
config.remove_section('topsecret.server.com')
config.write(open(r".\testfiles\config.conf",encoding='utf-8',mode='w'))
'''修改配置文件'''
config.read(r".\testfiles\config.conf",encoding='utf-8')
config.set("bitbucket.org", "user", "alex")
config.write(open(r".\testfiles\config.conf",encoding='utf-8',mode='w'))
'''删除某一节中的某一项'''
config = configparser.ConfigParser()
config.read(r".\testfiles\config.conf", encoding='utf-8')
config.remove_option("bitbucket.org", "user1")
f = open(r".\testfiles\config.conf",encoding='utf-8',mode='w')
config.write(f)
f.close()
六、re正则表达式模块
'''
string提供的方法是完全匹配
正则表达式是干嘛的?
进行模糊匹配
'''
import re
s = 'hello world'
res = re.findall(r'w\w{2}l', s)
print(res)
res = re.findall(r"alex", "dafsdafdaalexfdaksalexl")
print(res)
'''
表示重复的:元字符
. 匹配任意一个字符
^放在正则表达式起始位置表示匹配开头
$放在正则表达式末尾位置表示匹配结尾
*至少0次
+至少1次
?至多1次
表示字符集
[]字符集;取消元字符的特殊意义;\-^的意义不可以;^表示“除了”
'''
'''\b匹配一个特殊字符边界,也就是指单词和空格间的位置'''
print(re.findall(r'I\b', 'hello, I am a LI$T LI,st I#'))#['I', 'I', 'I']
'''匹配第一次满足条件的结果'''
res = re.search('sb', 'dafdafsbdhuifhuaisb')
print(res.group())
'''
正则表达式的方法:
findall():返回所有的结果到列表中
search():返回匹配到的第一个对象,调用group()获得结果
match():从指代字符串开头匹配
split():字符串分隔,分割使用的pattern不会出现在分割结果中
sub():匹配字符串进行替换
compile():正则表达式预编译
'''
'''match():从指代字符串开头匹配'''
res = re.match('asd', 'fdafadsd')
print(res)#未匹配道内容,使用group()会报错
res = re.match('asd', 'asdfdaf')
print(res.group())
'''split():'''
res = re.split('k', 'adskjh', 2)
print(res)
res = re.split('[k,s]', 'adskjh', 2)
print(res)#['ad', '', 'jh']
#下面这种,先根据k将字符串分成两部分,然后再根据s将两部分分别分开
res = re.split('[k,s]', 'sadkjhsrte', 4)
print(res)#['', 'ad', 'jh', 'rte']
'''sub():'''
res = re.sub('a..x', 'sb','replstringcountflagkx')
print(res)
'''compile()'''
comp = re.compile('\.com')
res = comp.split('zihan_lucky@163.com2434168561@qq.com;')
print(res)
注意:贪婪匹配和最小匹配
match = re.serch(r"PY.*N", 'PYANANANANCSDN')
match.group(0)
r'''
默认情况下为贪婪匹配,所以会从头匹配到结尾,匹配结果是PYANANANANCSDN
'''
match = re.serch(r"PY.*?N", 'PYANANANANCSDN')
match.group(0)
r'''
在*后加?则为最小匹配,匹配结果为PYAN
'''
操作符 | 说明 |
*? | 前一个字符0次或者无限次扩展,最小匹配 |
+? | 前一个字符1次或者无限次扩展,最小匹配 |
?? | 前一个字符0次或者1次扩展,最小匹配 |
{m,n}? | 扩展前一个字符m至n次(包括n),最小匹配 |
示例:简单计算器
这个实例实现了一个简单的计算机用来处理计算有括号的加减乘除混合运算,并最终得出计算结果。初学python,代码难免有点啰嗦,输入字符需要全是英文字符。
import re
# s = '1 - 2 * ( ( 60 -30 + ( -40/5 ) * ( 9 - 2 * 5 / 3 + 7 / 3* 99/ 4 *29 9 8 + 10*568 /1 4 ) ) -( - 4 * 3 ) /( 1 6 -3 * 2) )'
# s = '1+1'
s = '1*3+3*6-6/3-(2-1)'
print(eval(s))
'''计算乘除加减'''
def GeneralCal(s):
num = 0
if '(' in s or ')' in s or '(' in s or ')' in s : #去掉括号
s = re.sub('[((]', '',s)
s = re.sub('[))]', '',s)
s = s.replace('--','+')
s = s.replace('+-','-')
s = s.replace('++','+')
s = s.replace('-+','-')
print('s>>>',s)
seq = []
if '+' in s or '-' in s:
seq = re.split('[+-]', s)#按照+-符号将字符串分开
for val in seq:
# print(val.strip())
if '*' in val or '/' in val:
md = re.split('[*/]',val)
chmd = re.split('[^*/]',val)
chmd = ''.join(chmd)
num = float(md.pop(0))
i = 0
for v in md:
num1 = float(v)
if chmd[i] == '*':
num = num * num1
elif chmd[i] == '/':
num = num / num1
i += 1
s = s.replace(val.strip(),str(num))
s = s.replace('--','+')
s = s.replace('+-','-')
s = s.replace('++','+')
s = s.replace('-+','-')
chpr = []
if '+' in s or '-' in s:
chpr = re.split('[^+-]', s)
chpr = ''.join(chpr)
if len(chpr) == 0:
return s
seq = re.split('[+-]', s)#按照+-符号将字符串分开
if len(seq) == len(chpr) and len(chpr)== 1:
print(chpr)
return s
num = float(seq.pop(0))
i = 0
for v in seq:
num1 = float(v)
if chpr[i] == '+':
num = num + num1
elif chpr[i] == '-':
num = num - num1
i += 1
s = s.replace(val.strip(),str(num))
return num
'''去空格'''
def rmSpace(s):
s = str(s)
seq = s.split(' ')
s = ''.join(seq)
return s
s = rmSpace(s)
print(s)
#1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))
def rmPt(s):
while '(' in s:
res = re.findall('\([^()]+\)', s)#用来匹配最内层的括号
for value in res:
num = GeneralCal(value)
s = s.replace(value, str(num))
return GeneralCal(s)
print(rmPt(s))
七、random随机模块
import random
print(random.random())#产生一个[0,1)的随机数
print(random.randint(1,8))#产生一个[1,8]的随机数
'''
random.randrange ([start,] stop [,step])
start -- 指定范围内的开始值,包含在范围内。默认为1
stop -- 指定范围内的结束值,不包含在范围内。
step -- 指定递增基数。
randrange(100, 1000, 2)
'''
print(random.randrange(1,8))#产生一个[1,8)的随机数
# # 从 1-100 中选取一个奇数
print (random.randrange(1, 100, 2))
print(random.choice('hello'))#从序列中获取一个随机元素
print(random.choice(['123',4,[1,2]]))
lis = [16, 5, 10, 20,4,[1,2]]
random.shuffle(lis)#将序列的所有元素随机排序
print(lis)
print(random.sample(['123',4,[1,2]],2))#在序列中随机选两个
示例:随机生成五位验证码
'''
生成一个5位的验证码
1.直观版本
2.直接生成数字 chr()
'''
def vCode():
mcode=''
mnumbers=[str(x) for x in range(10)]
mch = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
mch.extend(mnumbers)
random.shuffle(mch)
# 随机抽取五个元素
length = len(mch)
for i in range(5):
mcode = ''.join([mcode,mch[random.randrange(length)]])
i+=1
# 随机抽取五个元素
mcode = ''.join(random.sample(mch,5))
return mcode
print(vCode())
'''
让数字和字母的ASCII码随机,从而产生随机数
'''
def vCode1():
mcode = ''
for i in range(5):
i += 1
asc = random.choice([random.randint(48,57),random.randint(65,90),random.randint(97,122)])
mcode = ''.join([mcode,chr(asc)])
return mcode
print(vCode1())
八、time时间模块
'''
时间模块:This module provides various functions to manipulate time values.
'''
import time,datetime
print(help(time))
print(time.time())#时间戳,1970年1月1日0点开始计算
print(time.get_clock_info(str))
time.sleep(1)
'''
https://www.cnblogs.com/weststar/p/11384291.html
time.struct_time(
tm_year=2020, 年
tm_mon=2, 月
tm_mday=18, 日
tm_hour=7, 时
tm_min=49, 分
tm_sec=20, 秒
tm_wday=1, 周2,从0开始计
tm_yday=49, 今年的第49天
tm_isdst=0)夏令时
'''
print(time.gmtime())#格林尼治时间UTC,结构化时间
print(time.localtime())#本地时间
struct_time = time.localtime()
'''
格式化时间
'''
print(time.strftime("1 %Y-%m-%d %H:%M:%S",struct_time))#2020-02-18 16:09:47
print(time.strftime("2 %a %A"))#Tue Tuesday
print(time.strftime("3 %b %B"))#Feb February
print(time.strftime("4 %c"))#Tue Feb 18 16:09:47 2020
print(time.strftime("5 %I"))#12小时计时
print(time.strftime("6 %p"))#AM or PM.
'''
输出为一个元组
time.struct_time(tm_year=2020, tm_mon=2, tm_mday=18, tm_hour=16, tm_min=9, tm_sec=47, tm_wday=1, tm_yday=49, tm_isdst=-1)
'''
print(time.strptime("2020-02-18 16:09:47", "%Y-%m-%d %H:%M:%S"))
tt = time.strptime("2020-02-18 16:09:47", "%Y-%m-%d %H:%M:%S")
print(tt.tm_year)
print(tt.tm_mon)
print(tt.tm_mday)
'''
将时间戳转化为默认格式化的时间
'''
print(time.ctime())#Tue Feb 18 16:17:34 2020
print(time.strftime("%c"))#Tue Feb 18 16:17:34 2020
print(time.ctime(1231231212))#Tue Jan 6 16:40:12 2009
'''
将time.struct_time(tm_year=2020, tm_mon=2, tm_mday=18, tm_hour=16, tm_min=21, tm_sec=8, tm_wday=1, tm_yday=49, tm_isdst=0)
转化为一个时间戳
'''
print(time.localtime())
print(time.mktime(time.localtime()))
'''
默认格式化的时间
'''
print(datetime.datetime.now())#2020-02-18 16:23:17.519090
九、模块描述
'''
包用来组织模块
模块用来组织包
__init__.py文件用来区分这个目录是文件夹还是一个包
在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护。
为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。在Python中,一个.py文件就称之为一个模块(Module)
使用模块有什么好处?
最大的好处是大大提高了代码的可维护性。
其次,编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用。我们在编写程序的时候,也经常引用其他模块,包括Python内置的模块和来自第三方的模块。
另外,使用模块还可以避免函数名和变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中,因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。但是也要注意,尽量不要与内置函数名字冲突。
所以,模块一共三种:
python标准库
第三方模块
应用程序自定义模块
引用模块
from 包名 import 模块名 as 别名
from 模块名 import 方法名 as 别名
import 模块名 as 别名
'''
9.1、__file__变量
import os,sys
'''获取当前项目的绝对路径'''
fpath = os.path.abspath(__file__)#__file__是当前文件的相对路径,abspath()获取绝对路径
parfpath = os.path.dirname(fpath)#获取当前文件的父目录的绝对路径
grandparfpath = os.path.dirname(parfpath)#获取项目的绝对路径
print(grandparfpath)
'''解决多包下的程序移植后路径找不到的问题'''
syspath = sys.path
syspath.insert(1, grandparfpath)#将项目绝对路径插入到系统模块的搜索路径列表中
print(syspath)
9.2、__name__变量
print(__name__)
def hello():
print('hello')
'''
做测试模块之用
在别处__name__是:day9.new3__name__
只有在当前模块内运行__name__才是:__main__
'''
if __name__ == '__main__':#本模块被别的模块引用的时候,这条语句下面的语句将不会被执行
hello()
十、软件目录结构规范
'''
Foo/
|-- bin/
| |-- foo
|
|-- foo/
| |-- tests/
| | |-- __init__.py
| | |-- test_main.py
| |
| |-- __init__.py
| |-- main.py
|
|-- docs/
| |-- conf.py
| |-- abc.rst
|
|-- setup.py
|-- requirements.txt
|-- README
说明
bin/: 存放项目的一些可执行文件,当然你可以起名script/之类的也行。
foo/: 存放项目的所有源代码。(1) 源代码中的所有模块、包都应该放在此目录。不要置于顶层目录。(2) 其子目录tests/存放单元测试代码; (3) 程序的入口最好命名为main.py。
docs/: 存放一些文档。
setup.py: 安装、部署、打包的脚本。
requirements.txt: 存放软件依赖的外部Python包列表。
README: 项目说明文件。
'''
十一、数据序列化
11.1、json模块(字典等数据序列化)
'''
序列化
'''
import json
'''字典序列化,写入到文件'''
dic={'name':'alvin','age':23,'sex':'male'}
dat = json.dumps(dic)
print(dat)
f = open('json_test.json',mode='w',encoding='utf-8')
f.write(dat)
f.close()
'''
从文件中读取
'''
f = open('json_test.json',encoding='utf-8',mode='r')
dat = f.read()
dic = json.loads(dat)
print(type(dic),dic)
'''
函数和类都不是json可以序列化的对象,需要使用pickle
'''
def foo():
print('ok')
json.dumps(foo)#Object of type function is not JSON serializable
'''
dump()序列化并写入文件
load()从文件中读取并转化为对象
'''
f = open('json_test.json',mode='w',encoding='utf-8')
dic={'name':'alvin','age':24,'sex':'male'}
# dat = json.dumps(dic)
# f.write(dat)
json.dump(dic,f)#序列化并写入文件
f.close()
f = open('json_test.json',encoding='utf-8',mode='r')
# dat = f.read()
# dic = json.loads(dat)
dic = json.load(f)#从文件中读取并转化为对象
f.close()
print(type(dic),dic)
11.2、pickle模块(函数序列化)
import pickle
dic={'name':'alvin','age':23,'sex':'male'}
dat = pickle.dumps(dic)
print(dat)
f = open('pickle_test.json',mode='wb')
'''
f = open('pickle_test.json',mode='w')
write() argument must be str, not bytes
'''
f.write(dat)
f.close()
f = open('pickle_test.json',mode='rb')
dat = f.read()
dic = pickle.loads(dat)
print(type(dic),dic)
def foo():
print('ok')
dat = pickle.dumps(foo)
f = open('pickle_test.json',mode='wb')
f.write(dat)
f.close()
'''
写入和读取的双方都要有同一个函数,该函数对象才能被读取出来
'''
f = open('pickle_test.json',mode='rb')
dat = f.read()
func = pickle.loads(dat)
print(type(func))
func()#调用读取出来的函数
11.3、shelve模块
'''
shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以是python所支持的数据类型
python错误之db type could not be determined
解决:不能手动创建文件,让代码自动创建。
'''
import shelve
f = shelve.open(r'shelve_inf.txt')
f['stu1_info']={'name':'alex','age':'18'}
f['stu2_info']={'name':'alvin','age':'20'}
f['school_info']={'website':'oldboyedu.com','city':'beijing'}
f.close()
print(f.get('stu1_info')['age'])
十二、xml模块
from xml.etree import ElementTree as ET
'''
xml文件的读取
XML文件解析的两种方式:
a.解析字符串方式
b.解析文件方式
'''
'''a.解析字符串方式'''
str_xml = open('XML_test.xml', 'r').read()# 打开文件,读取XML内容
root = ET.XML(str_xml)# 将字符串解析成xml特殊对象,root代指xml文件的根节点,print(root)将获取根节点的内存地址,print(root.tag)可以获取根节点的名称
print(root,root.tag)
print(type(str_xml),'\n',str_xml)#print(str_xml)则获得整个xml文件中的内容,str_xml是个字符串
'''b.解析文件方式'''
tree = ET.parse("XML_test.xml")# 直接解析xml文件
root = tree.getroot()# 获取xml文件的根节点
print(root,root.tag)
'''遍历标签的所有内容'''
tree = ET.parse('XML_test.xml')
root = tree.getroot()
print(root.tag,root.attrib,root.text)
for child in root:
print(child.tag,child.attrib,child.text)
for val in child:
print(val.tag,val.attrib,val.text)
'''遍历标签的指定节点'''
tree = ET.parse('XML_test.xml')
root = tree.getroot()
for child in root.iter('neighbor'):
print(child.tag,child.attrib,child.text)
'''
修改节点内容:由于修改节点时,都在内存中进行,不会影响原文件中的内容。如果想要保存修改,则会要将内存中的内容写入文件。
a.解析字符串方式的修改和保存
b.解析文件方式的修改和保存
'''
'''a.解析字符串方式的修改和保存'''
str_xml = open('XML_test.xml', mode='r',encoding='utf-8')#打开文件
root = ET.XML(str_xml.read())#将字符串解析为xml对象
for val in root.iter('year'):
#将year节点中的内容增加1
v = int(val.text)+1
val.text = str(v)
#设置属性
val.set('name','alex')
val.set('age','36')
del val.attrib['updated']
tree = ET.ElementTree(root)
tree.write('new1.xml', encoding='utf-8')
str_xml.close()
'''b.解析文件方式的修改和保存'''
tree = ET.parse('XML_test.xml')
root = tree.getroot()
for val in root.iter('year'):
#将year节点中的内容增加1
v = int(val.text)+2
val.text = str(v)
#设置属性
val.set('name','alex')
val.set('age','36')
del val.attrib['updated']
tree.write('new1.xml', encoding='utf-8')
'''
删除节点
'''
tree = ET.parse('XML_test.xml')
root = tree.getroot()
for child in root.findall('country'):
rank = int(child.find('rank').text)
if rank > 50:
root.remove(child)
tree.write('new2.xml', encoding='utf-8')
'''创建xml文件的三种方式'''
'''第一种方式'''
root = ET.Element('方便面')
fbm1 = ET.Element('fbm',{'名称':'康师傅'})
fbm2 = ET.Element('fbm',{'名称':'大今野'})
kouwei1 = ET.Element('kouwei',{'口味':'老坛酸菜'})
kouwei2 = ET.Element('kouwei',{'口味':'红烧牛肉'})
fbm1.append(kouwei1)
fbm2.append(kouwei2)
root.append(fbm1)
root.append(fbm2)
tree = ET.ElementTree(root)
tree.write('fbmBrand.xml', encoding='utf-8')
'''第二种'''
root = ET.Element('方便面')
fbm1 = root.makeelement('fbm',{'名称':'康师傅'})
fbm2 = root.makeelement('fbm',{'名称':'大今野'})
kouwei1 = root.makeelement('kouwei',{'口味':'老坛酸菜'})
kouwei2 = root.makeelement('kouwei',{'口味':'红烧牛肉'})
fbm1.append(kouwei1)
fbm2.append(kouwei2)
root.append(fbm1)
root.append(fbm2)
tree = ET.ElementTree(root)
tree.write('fbmBrand.xml', encoding='utf-8')
'''第三种'''
root = ET.Element('方便面')
fbm1 = ET.SubElement(root, 'fbm', {'名称':'康师傅'})
fbm2 = ET.SubElement(root, 'fbm', {'名称':'大今野'})
kouwei1 = ET.SubElement(fbm1, 'kouwei', {'口味':'老坛酸菜'})
kouwei2 = ET.SubElement(fbm2, 'kouwei', {'口味':'红烧牛肉'})
tiaoliaobao = ET.SubElement(kouwei1, 'tiaoliao', {'调料包':'酸菜包'})
tiaoliaobao.text = '没有,惊不惊喜!'
tree = ET.ElementTree(root)
tree.write('fbmBrand.xml', encoding='utf-8')
from xml.dom import minidom
def prettify(elem):
"""将节点转换成字符串,并添加缩进。
"""
rough_string = ET.tostring(elem, encoding='utf-8')
reparsed = minidom.parseString(rough_string)
return reparsed.toprettyxml(indent="\t")
# 创建根节点
root = ET.Element('方便面')
fbm1 = ET.SubElement(root, 'fbm', {'名称':'康师傅'})
fbm2 = ET.SubElement(root, 'fbm', {'名称':'大今野'})
kouwei1 = ET.SubElement(fbm1, 'kouwei', {'口味':'老坛酸菜'})
kouwei2 = ET.SubElement(fbm2, 'kouwei', {'口味':'红烧牛肉'})
tiaoliaobao = ET.SubElement(kouwei1, 'tiaoliao', {'调料包':'酸菜包'})
tiaoliaobao.text = '没有,惊不惊喜!'
raw_str = prettify(root)
f = open("fbmBrand.xml",'w',encoding='utf-8')
f.write(raw_str)
f.close()
十三、参考文章