Python3基础-os、sys、json、pickle、shelve、xml模块
1、os 模块
脚本的目录结构 |-pyAuto | |---pythonDay | |--pythonbase | |---web | |--os模块.py
os.path.dirname(path) 返回文件路径
去掉文件名,返回目录
import os print("输出当前文件的路径:",__file__) #__file__表示当前.py文件的绝对路径: BASE_dir = os.path.dirname(__file__) #去掉文件名,返回目录 print(BASE_dir) BASE_dir = os.path.dirname("D:/pyAuto/pythonDay/pythonbase") #返回上一级的目录 print(BASE_dir)
执行结果如下:
输出当前文件的路径: D:/pyAuto/pythonDay/pythonbase/随机模块.py D:/pyAuto/pythonDay/pythonbase D:/pyAuto/pythonDay
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir() 改变当前脚本工作目录
os.curdir 返回当前目录(‘.’)
os.pardir 获取当前目录的父目录字符串名(‘..’)
#os.getcwd() print("获取当前工作目录,即当前python脚本工作的目录路径",os.getcwd()) #os.chdir() os.chdir("D:\pyAuto\pythonDay\pythonbase\web") #绝对路径 print("切换进入web目录,获取当前脚本工作目录",os.getcwd()) #返回上一级 os.chdir("..") print("获取当前脚本工作目录",os.getcwd()) #再切换至web目录下 os.chdir("web") #相对路径 print("获取当前脚本工作目录",os.getcwd()) #os.curdir 返回当前目录 os.chdir(os.curdir) #返回当前目录os.chdir('.') print("获取当前脚本工作目录",os.getcwd()) #os.pardir 获取当前目录的父目录字符串名 os.chdir(os.pardir) #相当于 os.chdir('..') 返回上一级 print("获取当前目录的父目录字符串名",os.getcwd())
执行结果如下:
获取当前工作目录,即当前python脚本工作的目录路径 D:\pyAuto\pythonDay\pythonbase 切换进入web目录,获取当前脚本工作目录 D:\pyAuto\pythonDay\pythonbase\web 获取当前脚本工作目录 D:\pyAuto\pythonDay\pythonbase 获取当前脚本工作目录 D:\pyAuto\pythonDay\pythonbase\web 获取当前脚本工作目录 D:\pyAuto\pythonDay\pythonbase\web 获取当前目录的父目录字符串名 D:\pyAuto\pythonDay\pythonbase
os.makedirs()生成多层递归目录
os.removedirs()若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir() 生成单级目录
os.rmdir() 删除单级目录 ;若目录不为空则无法删除
os.makedirs('dirname1/dirname2') os.chdir("D:\pyAuto\pythonDay\pythonbase\dirname1\dirname2") print("获取当前目录的父目录字符串名",os.getcwd()) os.chdir("D:\pyAuto\pythonDay\pythonbase") #print("获取当前目录的父目录字符串名",os.getcwd()) #os.removedirs() 删除目录 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推 os.removedirs('dirname1/dirname2') #print("获取当前目录的父目录字符串名",os.getcwd()) #创建dirname1目录后再删除dirname1目录 os.mkdir('dirname1') os.rmdir('dirname1') #删除单级目录 若目录不为空则无法删除 报错 OSError: [WinError 145] 目录不是空的。
#在web目录下创建一个11.txt文件后,返回上一级再删除11.txt文件
##在web目录下创建一个11.txt文件后,返回上一级再删除11.txt文件 os.chdir("D:\pyAuto\pythonDay\pythonbase\web") with open('11.txt','w+') as f: f.write('aaaa') print('列出当前目录下所有文件和子目录',os.listdir('.')) os.rename('11.txt','22.txt') print('列出当前目录下所有文件和子目录',os.listdir('.')) #列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印 print('获取文件/目录信息',os.stat('22.txt')) #获取文件/目录信息 os.chdir('..') os.remove('web/22.txt') #删除一个文件 print('列出当前目录下所有文件和子目录',os.listdir())
以上执行结果如下:
列出当前目录下所有文件和子目录 ['11.txt'] 列出当前目录下所有文件和子目录 ['22.txt'] 获取文件/目录信息 os.stat_result(st_mode=33206, st_ino=9288674231524105, st_dev=311216978, st_nlink=1, st_uid=0, st_gid=0, st_size=4, st_atime=1572331776, st_mtime=1572331776, st_ctime=1572331776)
#os.listdir()
print('列出当前目录下所有文件和子目录',os.listdir())
"""
执行结果如下
列出当前目录下所有文件和子目录 ['11', 'a.txt', 'aa.txt', 'color.py', 'Day.py', 'Day1.py', 'demoA.py', 'fet.conf', 'filedb', 'os模块.py', 'sed.py', 'sed_new.bak.py', 'test.py', 'test1.py', 'time.py', 'web', '__pycache__', '字符编码', '文件读写操作.py', '生产者和消费者.py', '装饰器.py', '迭代器.py', '随机模块.py']
"""
print('输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"=========',os.sep) print('输出当前平台使用的行终止符,win下为"\\t\\n",Linux下为"\\n"=========',os.linesep) print('输出用于分割文件路径的字符串 win下为;,Linux下为: =========',os.pathsep) print('输出字符串指示当前使用平台。win->"nt"; Linux->"posix"',os.name) print('获取系统环境变量',os.environ) print(os.system("dir")) #运行shell命令,直接显示 print(os.path.abspath('web')) #D:\pyAuto\pythonDay\pythonbase\web 返回path规范化的绝对路径 print(os.path.split('web')) # 将path分割成目录和文件名二元组返回 ('', 'web') print(os.path.split(r'D:\pyAuto\pythonDay\pythonbase\web')) #('D:\\pyAuto\\pythonDay\\pythonbase', 'web') print(os.path.split(r'D:\pyAuto\pythonDay\pythonbase\sed.py')) #('D:\\pyAuto\\pythonDay\\pythonbase', 'sed.py') print(__file__)#D:/pyAuto/pythonDay/pythonbase/os模块.py print(os.path.dirname(__file__)) #返回path的目录。其实就是os.path.split(path)的第一个元素 D:/pyAuto/pythonDay/pythonbase print(os.path.basename(__file__)) #os模块.py 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素 print(os.path.basename(r'D:\pyAuto\pythonDay\pythonbase\web')) #web print(os.path.basename('web/')) #空置 print(os.path.exists(__file__)) # 如果path存在,返回True; print(os.path.exists('D:\pyAuto\pythonDay\pythonbase\web1')) #path不存在,则返回False print(os.path.isabs('web')) #相对路径,则返回False print(os.path.isabs(__file__)) #绝对路径,则返回True print(os.path.isfile(__file__)) #path是一个存在的文件,返回True print(os.path.isfile('D:\pyAuto\pythonDay\pythonbase\web')) #目录路径,则返回False print(os.path.isdir(__file__)) #path是一个存在的文件,返回False print(os.path.isdir('D:\pyAuto\pythonDay\pythonbase\web'))#path是一个存在的目录,返回Frue print(os.path.getatime(__file__)) # 返回path所指向的文件或者目录的最后存取时间 print(os.path.getctime(__file__)) # 返回path所指向的文件或者目录的最后修改时间 path1 = 'D:\pyAuto\pythonDay' path2 = 'pythonbase\web' print(os.path.join(path1,path2)) #路径拼接 D:\pyAuto\pythonDay\pythonbase\web
2、sys模块
sys.argv[]
是用来获取命令行输入的参数的(参数和参数之间空格区分),sys.argv[0]表示代码本身文件路径,所以从参数1开始,表示获取的参数了
#sys_test.py
import sys a=sys.argv[0] print(a)
进入cmd 运行该sys_test.py文件
sys.argv[0]指代码(即此.py程序)本身的意思。
然后我们将代码中0改为1 :
a=sys.argv[1]
保存,再次从控制台窗口运行,加上一个参数 a
再次修改代码:
a=sys.argv[1:]
Sys.argv[ ]其实就是一个列表,里边的项为用户输入的参数,关键就是要明白这参数是从程序外部输入的,而非代码本身的什么地方,要想看到它的效果就应该 将程序保存了,从外部来运行程序并给出参数。
sys.version
print(sys.version) #获取python解释程序的版本信息 ”“” 执行结果 3.7.4 (tags/v3.7.4:e09359112e, Jul 8 2019, 19:29:22) [MSC v.1916 32 bit (Intel)] “”“
sys.exit()
会引发一个异常:SystemExit,如果这个异常没有被捕获,那么python解释器将会退出。如果有捕获此异常的代码,那么这些代码还是会执行。
import sys try: sys.exit(0) except: print('bug...') finally: print('ooooooo')
执行结果如下
bug... ooooooo
sys.exit()的退出比较优雅,调用后会引发SystemExit异常,可以捕获此异常做清理工作
sys.maxsize
python3 运行sys.maxint 报错
print(sys.maxint) #AttributeError: module 'sys' has no attribute 'maxint'
获取最大的值用sys.maxsize
print(sys.maxsize) #输出 2147483647
sys.path
print(sys.path) #返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 """ ['D:\\pyAuto\\pythonDay\\pythonbase', 'D:\\pyAuto', 'D:\\Work_software\\PyCharm 2019.1.3\\helpers\\pycharm_display', 'D:\\python37\\python37.zip', 'D:\\python37\\DLLs', 'D:\\python37\\lib', 'D:\\python37', 'D:\\python37\\lib\\site-packages', 'D:\\Work_software\\PyCharm 2019.1.3\\helpers\\pycharm_matplotlib_backend'] """
sys.platform
print(sys.platform) #返回操作系统平台名称 win32
sys.stdin.readline()与input
import sys # sys.stdin.readline() 相当于input,区别在于input不会读入'\n' aa = sys.stdin.readline() bb = input('请输入:') print(len(aa))print(len(bb)) """ 执行结果 hello 请输入:hello 6 5 """
在平时使用sys.stdin.readline( )获取输入的话,不要忘了去掉末尾的换行符,可以用strip( )函数(sys.stdin.readline( ).strip('\n'))或sys.stdin.readline( )[:-1]
sys.stdout与print
sys.stdout.write('hello' + '\n') print('hello') """ 执行结果 hello hello """
进度条 demo
import sys,time for i in range(100): sys.stdout.write('#') time.sleep(0.1) sys.stdout.flush() #刷新缓冲区
百分比进度条
#百分比进度条 import sys import time def view_bar(num,total): rate = num/total rate_num = int(rate *100) r = '\r[%s%s]%d%%'%("="*num," "*(100-num),rate_num,) sys.stdout.write(r) sys.stdout.flush() for i in range(0,101): time.sleep(0.1) view_bar(i,100)
3、json模块&pickle
python 中用于序列化的两个模块
- json 用于【字符串】和 【python基本数据类型】 间进行转换
- pickle 用于【python特有的类型】 和 【python基本数据类型】间进行转换
Json模块提供了四个功能:dumps、dump、loads、load
pickle模块提供了四个功能:dumps、dump、loads、load
3.1 json 模块
- json.load()从文件中读取json字符串
- json.loads()将json字符串转换为字典类型
- json.dumps()将python中的字典类型转换为字符串类型
- json.dump()将json格式字符串写到文件中
import json # Python 字典类型转换为 JSON 对象 data = { 'code': 10010, 'message': 'Try again', 'url': 'http://www.runoob.com' } json_str = json.dumps(data) print("Python 原始数据:", repr(data)) print("JSON 对象:", json_str) # 将 JSON 对象转换为 Python 字典 data2 = json.loads(json_str) print ("data2['code']: ", data2['code']) print ("data2['url']: ", data2['url']) """ 执行结果 Python 原始数据: {'code': 10010, 'message': 'Try again', 'url': 'http://www.runoob.com'} JSON 对象: {"code": 10010, "message": "Try again", "url": "http://www.runoob.com"} data2['code']: 10010 data2['url']: http://www.runoob.com """
处理文件-写入文件
import json with open('test.json','w+') as f: data = { 'code': 10010, 'message': 'Try again', 'url': 'http://www.runoob.com' } json.dump(data, f) # 将json格式字符串写到文件中 成功 {"code": 10010, "message": "Try again", "url": "http://www.runoob.com"}
处理文件-读取文件内容
with open('test.json','r+') as f: data=json.load(f) #从文件中直接读取json字符串 该文件只有一行 print("data2['code']: ", data['code']) #当test,json 文本内容多行json数据 #data=json.load(f) json.decoder.JSONDecodeError: Extra data: line 2 column 1 (char 72)
#文件内容存在多行
with open('test.json','r+') as f: for line in f.readlines(): data = json.loads(line) #将读取到的line转换python数据类型 print(data)
json 和python 内置的数据类型转换
a = 1 #int b_list = [1,2,3,4] #列表 b_tup=(1,2,3,4) #元祖 c_str='hello' #字符串 dic ={"name":"susu"} #python 数据类型转换json 字符串 json_a = json.dumps(a) json_list = json.dumps(b_list) json_tup = json.dumps(b_tup) json_str = json.dumps(c_str) json_dic = json.dumps(dic) print(type(json_a),type(json_list),type(json_tup),type(json_str),type(json_dic)) #将json 字符串转换成python 数据类型 python_a = json.loads(json_a) python_list= json.loads(json_list) python_tup= json.loads(json_tup) python_str= json.loads(json_str) python_dic= json.loads(json_dic) print(type(python_a),type(python_list),type(python_tup),type(python_str),type(python_dic))
执行结果如下:
<class 'str'> <class 'str'> <class 'str'> <class 'str'> <class 'str'> <class 'int'> <class 'list'> <class 'list'> <class 'str'> <class 'dict'>
3.2 pickle模块
如象存在于程序运行时的内存中,当程序不再运行时或断电关机时,这些对象便不再存在。现在想把对象保存下来,方便以后使用,这就是持久化技术。
利用 python标准库中的的pickle
模块可以将对象转换为一种可以传输或存储的格式
3.21 序列化-dump() 、dumps()
dump()方法
该方法的作用是实现python 对象的序列化,将 obj 保存到 file 中。
具体语法如下:
pickle.dump(obj, file[, protocol])
protocol: 可选的参数,默认为 0。0表示所序列化的对象使用可打印的ASCII码表示;1或True 表示使用老式的二进制协议;2表示使用python2.3版本引入的新二进制协议,比以前的高效;负值表示将使用可用的最高协议版本。
如果 protocol>=1
,那么文件对象需要以二进制形式打开。
import pickle dic={'name':'alvin','age':23,'sex':'male'} with open('序列化对象_pickle1','wb') as f: ##注意是w是写入str,wb是写入bytes, pickle.dump(dic,f)
dumps()
具体语法为:
pickle.dumps(obj[, protocol])
返回一个字符串,而不是存入文件中。
import pickle dic={'name':'alvin','age':23,'sex':'male'} with open('序列化对象_pickle2','wb') as f: data = pickle.dumps(dic) f.write(data) #-------------------等价于pickle.dump(dic,f)
3.21 反序列化-load() 、loads()
load()
该方法用于反序列化,即将序列化的对象重新恢复成python对象。
具体语法如下:
pickle.load(file)
这个 file 必须是一个拥有一个能接收单整数为参数的 read() 方法以及一个不接收任何参数的 readline() 方法,并且这两个方法的返回值都应该是字符串。这可以是一个打开为读的文件对象、StringIO 对象或其他任何满足条件的对象。
import pickle with open('序列化对象_pickle','rb') as f: data=pickle.load(f) #读取多行,也是不可以的 会出现报错 print(data) """ 执行结果 {'name': 'alvin', 'age': 23, 'sex': 'male'} """
loads()
pickle.loads(string)
从字符串中恢复对象。
import pickle with open('序列化对象_pickle','rb') as f: f_data = f.read() print(f_data) data = pickle.loads(f_data) print(data) """ 执行结果 b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x05\x00\x00\x00alvinq\x02X\x03\x00\x00\x00ageq\x03K\x17X\x03\x00\x00\x00sexq\x04X\x04\x00\x00\x00maleq\x05u.' {'name': 'alvin', 'age': 23, 'sex': 'male'} """
4、shelve模块
shelve是python中用来持久化存储的模块,类似于一个key-value的数据库,但是这里的value不限定类型,可以是python中任意的数据类型,也可以是自己定义的数据类型。
从shelve中取出的可变对象,在内存中发生更改时,shelve是无法知道的,也不会自动的把更改写回到文件(除非参数writeback设置为True,如果是这样,若数据较大时会消耗大量内存)。
添加一个元素到db[key]并且能起效应该是这样子(先读取在临时变量,再修改,最后写入)
import shelve with shelve.open("shelve_test") as f: #添加 f['name'] = 'susu' f['age'] = 12 f['study'] =['English','美术','语文'] f['info']={'who':'susu','where':'福建','why':1} #查看 print(f['name']) print(f['age']) print(f['study']) print(f['info'])
print(f['info']['where']) #修改字符串 f['name']= 'sugh' #将f['name']: susu 修改为 sugh print(f['name']) #修改成功 输出 sugh f['study'].append('数学') print(f['study']) #还是返回 ['English', '美术', '语文'] temp = f['study'] temp.append('数学') f['study'] = temp print(f['study']) #成功添加一个数学 ['English', '美术', '语文', '数学'] #删除 del f['name'] #判断是否含有‘name’ if 'name' in f: print('仍然存在') else: print('已经被删除了') #关闭shelve f.close()
执行结果如下:
susu 12 ['English', '美术', '语文'] {'who': 'susu', 'where': '福建', 'why': 1}
福建 sugh ['English', '美术', '语文'] ['English', '美术', '语文', '数学'] 已经被删除了
5、XML 模块
<?xml version="1.0"?> <bookstore> <book category="COOKING"> <title lang="en">Everyday Italian</title> <author>Giada De Laurentiis</author> <year>2005</year> <price>30.00</price> </book> <book category="CHILDREN"> <title lang="en">Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> <book category="WEB"> <title lang="en">Learning XML</title> <author>Erik T. Ray</author> <year>2003</year> <price>39.95</price> </book> </bookstore>
#解析1 调用parse()方法,返回解析树 python3.3之后ElementTree模块会自动寻找可用的C库来加快速度 tree = ET.parse("xmltest.xml") #<class 'xml.etree.ElementTree.ElementTree'> # print(tree) 返回<xml.etree.ElementTree.ElementTree object at 0x01490A10> root = tree.getroot() #获取根节点 #print(root) 返回<Element 'bookstore' at 0x039EB960> print(root.tag, ":", root.attrib) # 打印根元素的tag和属性 #解析2 调用from_string(),返回解析树的根元素 with open("xmltest.xml",'r') as f: data=f.read() root = ET.fromstring(data) print(root.tag, ":", root.attrib) #解析3 调用ElementTree类ElementTree(self, element=None, file=None) # 这里的element作为根节点 tree = ET.ElementTree(file="xmltest.xml") # <xml.etree.ElementTree.ElementTree object at 0x03031390> root = tree.getroot() # <Element 'data' at 0x030EA600> print(root.tag, ":", root.attrib)
5.2 遍历
1)简单遍历
# 遍历xml文档的第二层 for child in root: #第二层节点的标签名称和属性 print(child.tag, child.attrib) #遍历xml文档的第三层 for i in child: print('遍历xml文档',i.tag, i.text) # 只遍历year 节点 for node in root.iter('year'): print(node.tag, node.text) #通过下标的方式直接访问节点 year = root[0][2].text print('year ====:',year) year = root[1][2].text print('year ====:',year) year = root[2][2].text print('year ====:',year)
book {'category': 'COOKING'} 遍历xml文档 title Everyday Italian 遍历xml文档 author Giada De Laurentiis 遍历xml文档 year 2005 遍历xml文档 price 30.00 book {'category': 'CHILDREN'} 遍历xml文档 title Harry Potter 遍历xml文档 author J K. Rowling 遍历xml文档 year 2065 遍历xml文档 price 29.99 book {'category': 'WEB'} 遍历xml文档 title Learning XML 遍历xml文档 author Erik T. Ray 遍历xml文档 year 2003 遍历xml文档 price 39.95 year 2005 year 2065 year 2003 year ====: 2005 year ====: 2065 year ====: 2003
2)
ElementTree提供的方法
-
find
(match) # 查找第一个匹配的子元素, match可以时tag或是xpaht路径 -
findall
(match) # 返回所有匹配的子元素列表 -
findtext
(match, default=None) # -
iter
(tag=None) # 以当前元素为根节点 可以对某个元素对象之下所有的子元素进行深度优先遍历 如果tag不为None,则以tag进行过滤
-
iterfind
(match) # 则返回一个所有匹配元素的迭代器
# 遍历所有节点 for node in root.iter(): print('node.tag=',node.tag, 'note.text=',node.text,' ',end='') # 只遍历year 节点 for node in root.iter('year'): print(node.tag, node.text)
for node in root.iterfind('book/year'):
print('node.tag=', node.tag, 'note.text=', node.text, ' ', end='')
# 遍历所有的book标签 for book in root.findall("book"): # 查找book标签下的第一个rank标签 title = book.find("title").text # 获取book标签的category属性 name = book.get("category") print('title==',title,'name==',name) """ 执行结果 title== Everyday Italian name== COOKING title== Harry Potter name== CHILDREN title== Learning XML name== WEB """
5.3 修改xml 结构
# 所有的年份+1,并添加属性month为yes for node in root.iter('year'): new_year = int(node.text) + 1 node.text = str(new_year) #将int 转换为str node.set("month", "yes") #添加属性 # 再终端显示整个xml ET.dump(root) # 注意 修改的内容存在内存中 尚未保存到文件中 # 保存修改后的内容 tree.write("xmltest.xml")
# 删除node for book in root.findall('book'): print(book) Sprice = book.find('price').text price = int(float(Sprice)) print(price) if price > 30: #remove ()方法 删除子元素 root.remove(book) ET.dump(root) tree.write('output.xml')
#删除属性 for yaer in root.iter("year"): # attrib为属性字典 # 删除对应的属性updated del yaer.attrib['month'] ET.dump(root) tree.write('output.xml')
小结:
attrib 为包含元素属性的字典 keys() 返回元素属性名称列表 items() 返回(name,value)列表 get(key, default=None) 获取属性 set(key, value) # 跟新/添加 属性 del xxx.attrib[key] # 删除对应的属性
添加子元素
book = root[0] last_ele = book [len(list(book))-1] print('====',last_ele) last_ele.tail = '\n ' # 创建新的元素, tag为test_append elem1 = ET.Element("test_append") elem1.text = "elem 1" elem1.tail = '\n ' book .append(elem1) # SubElement() 其实内部调用的时append() elem2 = ET.SubElement(book, "test_subelement") elem2.text = "elem 2" elem2.tail = '\n ' # extend() elem3 = ET.Element("test_extend") elem3.text = "elem 3" elem3.tail = '\n ' elem4 = ET.Element("test_extend") elem4.text = "elem 4" elem4.tail = '\n ' book.extend([elem3, elem4]) # insert() elem5 = ET.Element("test_insert") elem5.text = "elem 5" elem5.tail = '\n ' book.insert(5, elem5) ET.dump(book) tree.write('output.xml')
5.4 创建
import xml.etree.ElementTree as ET from xml.dom import minidom def subElement(root, tag, text): ele = ET.SubElement(root, tag) ele.text = text def saveXML(root, filename, indent="\t", newl="\n", encoding="utf-8"): rawText = ET.tostring(root) dom = minidom.parseString(rawText) with open(filename, 'w') as f: dom.writexml(f, "", indent, newl, encoding) root = ET.Element("data") #方法1 插入子标签 to to = root.makeelement("to", {}) to.text = "peter" to.set("name","yes") to.set("year","No") root.append(to) #方法2 subElement(root, "from", "marry") subElement(root, "heading", "Reminder") subElement(root, "body", "Don't forget the meeting!") #方法3 test=ET.SubElement(root, "test",attrib={"susu":"ues"}) test.text='测试内容' # 保存xml文件 saveXML(root, "note.xml")