目录
8、enumerate()函数和推导式生成列表,操作每行增加行号
一、文件操作
前面写的程序数据没有实际的存储,执行完数据就消失了。
1、文本文件和二进制文件
(1)文本文档,储存的是普通的“字符”文本,python默认为unicode字符集(两个字节表示一个字符65536个),可以用记事本程序打开,但是,word编辑的文本不是文本文件;
(2)二进制文件把数据内容用“字节”进行存储,无法用记事本打开,必须使用专用的软件进行解码,常见的有:MP4视频文件、MP3音频文件、JPG图片、doc文档等
2、文件操作相关模块概述
创建文件对象open()
这个对象映射到实际的文件中
f = open(文件名,或者是录入全路径,打开方式)
当输入的是全路径时,前面可以加r,减少了“\”的输入让pychram知道它不是转义字符
r:读read模式
w:写write模式,如果文件不存在则创建,存在则重新写内容
a:追加模式,如果文件不存在则创建,如果文件存在,则在文件末尾追加内容;
b:二进制模式(可与其他模式组合使用)
+:读写模式(可与其他模式组合使用)
如果是bw是以二进制形式写文件
如果没有增加b,则是以字符形式处理文件
3、文件文本的写入
基本的文件写入操作:
(1)创建文件对象;
(2)写入数据;
(3)关闭文件对象,通过close关闭python进行的文件操作以及os操作系统打开的文件
只有操作程序才有调用硬盘,所以如果不调用操作系统的资源,还打开资源,就造成了资源的浪费,所以有必要进行关闭。
4、中文乱码问题的解决
当我在python里面写了这样一段代码,生成的b.txt文件内部产生的是一个乱码的结果
(1)常见的编码介绍
注:目前的项目用的普遍是UTF—8
python用unicode来编码,实际存储的时候可能用的是GBK,也有可能是UTF—8(图里有写错的地方,注意一下,python里面实际储存有可能是utf—8或者GBK)
(2)中文乱码问题:
编码的时候用的是unicode,但是实际储存的时候,windows和linux有区别
windows操作系统默认的编码是GBK,linux操作系统默认的编码是UTF—8
由于在windows操作系统中将文件储存为了GBK的形式,我们打开的时候也应该以GBk的格式打开:右击文件b.txt,选择file encoding,选择GBK
对于上述乱码的文件可以选择编码系统GBK即可正常显示文字
或者在代码里写出用utf—8来编码
f = open(r"b.txt", "w")
f.write("西安电子科技大学\n小星星\n18岁\n天下第一美")
f.close()
f = open(r"c.txt", "w", encoding="utf—8") #用utf—8进行编码
f.write("西安电子科技大学\n小星星\n18岁\n天下第一美")
f.close()
5、close()关闭文件流——try异常管理
由于文件底层是由操作系统控制的,所以我们打开文件对象必须显示调用close()方法关闭文件对象。当调用close()方法时,首先会把缓冲区数据写入文件,也可以直接调用flush(),再关闭文件,释放文件对象。
write()/writelines()写入数据
write(a):把字符串a写入到文件中;
writelines(b):把字符串列表写入文件中,换行符需要自己加
try:
f = open(r"c.txt", "a", encoding="utf—8")
print()
f.write("小星星\n")
exceopt BaseException as e:
print(e)
finally:
f.close()
当使用close()方法时,首先会把缓冲区数据写入文件,然后再关闭文件,释放资源
6、关闭流要点:_with上下文管理_现场还原
with上下文管理器可以自动管理上下文资源,不论什么原因跳出with块,都可以确保文件正常关闭,并且可以在代码执行文笔后自动还原进该代码块的现场
s = ["高宇星\n", "韩敏\n", "燕子\n", "胖头鱼\n"]
with open("c.txt", "w",encoding="utf—8") as f:
f.writelines(s)
7、文本文件的读取:
read([size])
从文件中读取size字符,并作为结果返回。如果没有size参数,则读取整个文件——从头到尾。
with open(r"e.txt", "r", encoding="utf—8") as f:
str = f.read()
print(str)
'''
I love you!
xidian
litterStar
'''
with open(r"e.txt", "r", encoding="utf—8") as f:
str = f.read(3)
print(str)
#压力大
readline()
读取一行内容作为结果返回。读取文件末尾,会返回字符串
with open(r"e.txt", "r",encoding="utf—8") as f:
for a in f:
print(a, end=" ") #end = “ ” ——不换行
'''
压力大
I love you!
xidian
litterStar0
'''
#另一种方法
with open(r"e.txt", "r", encoding="utf—8") as f:
while True:
fragement = f.readline()
if not fragement:
break
else:
print(fragement, end="")
'''
压力大
I love you!
xidian
litterStar
'''
readlines()
文本文件中,每一行作为一个字符串传入列表中,返回该列表
8、enumerate()函数和推导式生成列表,操作每行增加行号
a = ["小星星\n", "世界第一美\n", "超可爱\n"]
b = enumerate(a)
print(b) #<enumerate object at 0x0000021A384CE280> 枚举对象
print(list(b)) #[(0, '小星星\n'), (1, '世界第一美\n'), (2, '超可爱\n')]
#会以元组的形式返回列表中的内容,前面是索引,后面是元素
c = [temp + "#" + str(index) for index, temp in enumerate(a)]
#temp是enumerate生成器里对元素的定义,indes是索引,因为前面的都是字符串,index也需要强制转换为字符串格式
print(c)
#['小星星\n#0', '世界第一美\n#1', '超可爱\n#2']
#为了去掉转义字符\n,我们使用rstrip,就是去掉尾部指定信息
d = [temp.rstrip("\n") + "#" + str(index) for index, temp in enumerate(a)]
print(d)
#['小星星#0', '世界第一美#1', '超可爱#2']
with open(r"c.txt", "r", encoding="utf—8") as f:
lines = f.readlines()
print(lines)
#['高宇星\n', '韩敏\n', '燕子\n', '胖头鱼\n']
lines = [temp.rstrip("\n") +"#"+ str(index+1) for index, temp in enumerate(lines)]
print(lines)
#['高宇星#1', '韩敏#2', '燕子#3', '胖头鱼#4']
9、二进制文件的读取和写入
拷贝了一张图片,拷贝成功
with open(r"a.jpg", "rb") as f:
with open(r"a_copy.jpg", "wb") as w:
for lines in f.readlines():
w.write(lines)
print("图片拷贝完成")
10、文件对象常用方法和属性总结
seek(相对指针位置的偏移量,指针位置)
0:表示指针从头开始;
1:表示从当前位置开始计算;
2:表示从文件末尾开始计算
with open(r"e.txt", "r", encoding="utf—8") as f:
print("文件名是:{0}".format(f.name))
print(f.tell()) #查看指针位置
print("读取的内容是:{0}".format(f.readline()))
print(f.tell())
#print("读取的内容为{0}".format(f.readline()))
#从头开始读取
f.seek(0) #从头开始,且偏移量为0
print("读取的内容是:{0}".format(f.readline()))
f.seek(3) #指针位置没有写东西,默认从头开始,偏移量为3——即第一个汉字被跳过了
print("读取的内容为:{0}".format(f.readline()))
'''
文件名是:e.txt
0
读取的内容是:压力大
#在utf—8里面,一个汉字占3个字节,文件开头占一个字节,换行符占用一个字节,相当于1+3*3+1 = 11
11
#读取的内容为I love you!
读取的内容是:压力大
读取的内容为:力大
'''
11、使用pickle序列化
python中,一切皆对象,对象本质上就是一个“存储数据的内存块”;我们需要将“内存块的数据”保存到硬盘上,就必须进行对象的序列化和反序列化。
这样就可以使信息在磁盘和内存之间传输,甚至在网页之间传输。
序列化的核心就是将数据形式“串行化”。
序列化可以使用pickle模块
#将对象序列化到文件中
import pickle
with open("data.txt","wb") as f:
a1 = "可爱的星星呀"
a2 = "永远开心哦"
a3 = "永远幸福哦"
pickle.dump(a1,f)
pickle.dump(a2,f)
pickle.dump(a3,f)
with open("data.txt","rb") as f:
b1 = pickle.load(f)
b2 = pickle.load(f)
b3 = pickle.load(f)
print(b1, b2, b3)
#可爱的小星星 一定要天天快乐呀 ['不要哭泣', '一切都会变好的!']
print(id(a1))
#2401331729104
print(id(b1))
#2401375112304
#虽然内容都一样,但是反序列化的对象是新对象
12、csv文件的操作
用excle做了一张工资表,前两天整理电脑删掉了,醉了
复制粘贴到pycharm里面,是这样的
#测试csv文件的读取和写入
import csv
with open("工作簿1.csv", "r", encoding="utf—8") as f:
a_csv = csv.reader(f) #csv.reader()是个生成器哦!
#print(a_csv)
#<_csv.reader object at 0x000002EE52540580> 生成器只能调用一次,所以注释掉再用一次
print(list(a_csv))
#[['\ufeffID', '姓名', '年龄', '薪资'], ['1001', '高宇星', '18', '30000'], ['1002', '韩敏', '16', '35000'], ['1003', '胖头鱼', '17', '10252'], ['1004', '燕子', '19', '33560']]
#在一个大列表里把每一行信息写作一个小列表
for row in a_csv:
print(row)
'''
['\ufeffID', '姓名', '年龄', '薪资']
['1001', '高宇星', '18', '30000']
['1002', '韩敏', '16', '35000']
['1003', '胖头鱼', '17', '10252']
['1004', '燕子', '19', '33560']
'''
二、操作系统命令
1、os模块
os模块可以帮助我们直接对操作系统进行操作。我们可以直接调用系统的可执行文件、命令,直接操作文件、目录等。
(1)os调用操作系统文件和命令
<1>os 调用系统文件和命令
import os
os.system("notepad.exe") #调用记事本
os.system("regedit") #调用注册表
os.system("ping www.baidu.com") #ping网站,在python里面是乱码,不操作了,我把file encoding改成GBK之后,pycharm瘫痪了,哭了简直
#直接调用可执行的文件
os.startfile(r"C:\Program Files (x86)\Tencent\WeChat\WeChat.exe")
#这里的文件路径是通过右击微信选择属性看到的
<2>os模块操作文件
os模块常用的操作文件的方法
remove(path) 删除指定文件
rename(src,dest) 重命名文件或目录
os.rename("电影", "movie") #把文件夹“电影”改成movie”
stat(path) 返回文件的所有属性
print(os.stat("任务140.py")) #查看文件相关信息
#os.stat_result(st_mode=33206, st_ino=12103423998578021, st_dev=3166015284, st_nlink=1, st_uid=0, st_gid=0, st_size=989, st_atime=1617243729, st_mtime=1617243665, st_ctime=1617242648)
#可以看到文件所有的信息,文件的大小等等
listdir(path) 返回path目录下的文件和目录列表
dirs = os.listdir("movie") #列出movie的子目录
print(dirs)
#['日本', '欧美', '港台']
mkdir(path) 创建目录
os.mkdir("书籍") #创建一个目录,书籍,在当前的工作空间里创建了
makedirs(path1/path2/path3··) 创建多级目录
os.makedirs("电影/港台/周星驰") #创建了多级目录
os.makedirs("../音乐/港台/刘德华") #../表示在当前目录的上一级目录下面创建了一个文件
#File "D:\developer_tools\anaconda\lib\os.py
rmdir(path) 删除目录
os.rmdir("书籍") #相对路径是相对于当前的工作目录在python下把书籍这个文件删掉了
#创建了多级目录 在周星驰下面加了一个文件 “功夫”
os.removedirs("电影/港台/周星驰")#此时无法删除,因为文件夹不为空
Traceback (most recent call last):
File "D:/developer_tools/python/pythonProject/123.py", line 39, in <module>
os.removedirs("电影/港台/周星驰")
File "D:\developer_tools\anaconda\lib\os.py", line 241, in removedirs
rmdir(name)
OSError: [WinError 145] 目录不是空的。: '电影/港台/周星驰'
报错了,删除目录的时候只能删除空目录
removedirs(path1/path2/path3··)删除多级目录
os.removedirs("电影/港台/周星驰") #删除了多及目录
getcwd() 返回当前工作目录
print(os.getcwd()) #查看文件的工作空间
#D:\developer_tools\python\pythonProject
chdir(path) 把path设成当前工作目录
os.chdir("c:") #改变了工作空间 在c盘
print(os.getcwd())
os.mkdir("音乐")
#在c盘中创建目录成功
walk() 遍历目录树
os.walk()方法会返回一个3个元素的元组(dirpath, dirnames, filenames)
dirpath:要列出指定目录的路径
dirnames:目录下的所有文件夹
filenames:目录下的所有文件
import os
path = os.getcwd()
list_files = os.walk(path)
print(list_files)
#<generator object walk at 0x000002303D2BA248> #说明os.walk()是一个生成器啊!
#walk 函数返回三个元组dirpath——目录路径, dirnames——目录名, filenames——文件名
for dirpath, dirnames, filenames in list_files:
for dir in dirnames:
print(dir)
for file in filenames:
print(file)
'''
movie
任务148.py
港台
日本
欧美
周星驰
功夫.mp4
'''
######################把文件目录加上################################
import os
path = os.getcwd()
list_files = os.walk(path)
for dirpath, dirnames, filenames in list_files:
for dir in dirnames:
print(os.path.join(dirpath, dir))
for file in filenames:
print(os.path.join(dirpath, file))
'''
D:\developer_tools\python\pythonProject\test.os\movie
D:\developer_tools\python\pythonProject\test.os\任务148.py
D:\developer_tools\python\pythonProject\test.os\movie\港台
D:\developer_tools\python\pythonProject\test.os\movie\日本
D:\developer_tools\python\pythonProject\test.os\movie\欧美
D:\developer_tools\python\pythonProject\test.os\movie\港台\周星驰
D:\developer_tools\python\pythonProject\test.os\movie\港台\周星驰\功夫.mp4
'''
#####################将所有的东西都放在一个列表里#############################
import os
all_files = []
path = os.getcwd()
list_files = os.walk(path)
for dirpath, dirnames, filenames in list_files:
for dir in dirnames:
all_files.append(os.path.join(dirpath, dir))
for file in filenames:
all_files.append(os.path.join(dirpath, file))
print(all_files)
#['D:\\developer_tools\\python\\pythonProject\\test.os\\movie', 'D:\\developer_tools\\python\\pythonProject\\test.os\\任务148.py', 'D:\\developer_tools\\python\\pythonProject\\test.os\\movie\\港台', 'D:\\developer_tools\\python\\pythonProject\\test.os\\movie\\日本', 'D:\\developer_tools\\python\\pythonProject\\test.os\\movie\\欧美', 'D:\\developer_tools\\python\\pythonProject\\test.os\\movie\\港台\\周星驰', 'D:\\developer_tools\\python\\pythonProject\\test.os\\movie\\港台\\周星驰\\功夫.mp4']
sep 当前操作系统所使用的路径分隔符
import os
a = "获取文件和文件夹相关的想信息"
b = a.center(60, "*")
print(b)
print(os.name) #nt, windows返回的是nt,linux返回的是posix 可以通过OS.name来判断操作系统
print(os.sep) #返回分隔符,windows返回的是\ linux发挥的是/
print(repr(os.linesep)) #返回换行符,windows返回的是'\r\n',linux返回的是\n\
完整的,成体系的代码如下:
import os
a = "获取文件和文件夹相关的想信息"
b = a.center(60, "*")
print(b)
print(os.name) #nt, windows返回的是nt,linux返回的是posix 可以通过OS.name来判断操作系统
print(os.sep) #返回分隔符,windows返回的是\ linux发挥的是/
print(repr(os.linesep)) #返回换行符,windows返回的是'\r\n',linux返回的是\n\
print(os.stat("任务140.py")) #查看文件相关信息
#os.stat_result(st_mode=33206, st_ino=12103423998578021, st_dev=3166015284, st_nlink=1, st_uid=0, st_gid=0, st_size=989, st_atime=1617243729, st_mtime=1617243665, st_ctime=1617242648)
#可以看到文件所有的信息,文件的大小等等
a = "关于目录的操作"
b = a.center(60, "*")
print(b)
print(os.getcwd()) #查看文件的工作空间
#D:\developer_tools\python\pythonProject
#os.mkdir("书籍") #创建一个目录,书籍,在当前的工作空间里创建了
#os.rmdir("书籍") #相对路径是相对于当前的工作目录 在python下把书籍这个文件删掉了
#os.chdir("c:") #改变了工作空间 在c盘
#print(os.getcwd())
#os.mkdir("音乐")
#在c盘中创建目录成功
#os.makedirs("电影/港台/周星驰") #创建了多级目录
#os.removedirs("电影/港台/周星驰") #删除了多及目录
#os.makedirs("电影/港台/周星驰") #创建了多级目录 在周星驰下面加了一个文件 “功夫”
#os.removedirs("电影/港台/周星驰")
'''
Traceback (most recent call last):
File "D:/developer_tools/python/pythonProject/123.py", line 39, in <module>
os.removedirs("电影/港台/周星驰")
File "D:\developer_tools\anaconda\lib\os.py", line 241, in removedirs
rmdir(name)
OSError: [WinError 145] 目录不是空的。: '电影/港台/周星驰'
报错了,只能删除空目录
'''
#os.makedirs("../音乐/港台/刘德华") #../表示在当前目录的上一级目录下面创建了一个文件
#File "D:\developer_tools\anaconda\lib\os.py
#os.rename("电影", "movie")
dirs = os.listdir("movie") #列出movie的子目录
print(dirs)
#['日本', '欧美', '港台']
2、os.path模块
os.path模块
提供了目录相关(路径判断/切分/链接/文件夹遍历)的操作
import os
from os import path #这样的话,每句话里就不需要再打印os
print(path.isabs("d:/a.txt")) #判断是否是一个绝对路径
#True
print(path.isdir("d:/a.txt")) #判断是否是一个目录
#False
print(path.isfile("d:/a.txt")) #判断是否是一个文件
#True
print(path.exists("d:/a.txt")) #判断是否存在
#True
####################获得文件基本信息###########################
print(path.getsize("b.txt")) #获取文件的大小
#42
print(path.abspath("b.txt")) #获取文件的绝对路径
#D:\developer_tools\python\pythonProject\b.txt
print(path.dirname("d:/a.txt")) #获取文件的根目录
#d:/
print(path.getatime("b.txt")) #获取最后访问时间
#1617698622.5961854
print(path.getctime("b.txt")) #这个表示从1970年1月1日已经经过多少秒
#1617150774.058493
print(path.getmtime("b.txt")) #获取最后的修改时间
#1617168894.4296467
###################对路径的操作#############################
path = os.path.abspath("b.txt")
print(os.path.split(path)) #将路径以进行切割
#('D:\\developer_tools\\python\\pythonProject', 'b.txt')
#返回的是元组,第一个元素是目录,第二个元素是文件名
print(os.path.splitext(path)) #返回的是拓展名,将拓展名和前面的东西分开了
#('D:\\developer_tools\\python\\pythonProject\\b', '.txt')
print(os.path.join("aa", "bb", "cc"))
#aa\bb\cc
#以分隔符的形式将字符串连在一起
########################练习##################################
#列出工作目录下所有的.py文件,并输出文件名
import os
path = os.getcwd()
file_list = os.listdir(path) #列出子目录,子文件
for filename in file_list:
if filename.endswith("py"): #做一个简单的判断,筛选python文件
print(filename)
'''
任务.py
任务140.py
任务142.py
任务143.py
任务144.py
任务145 os模块.py
任务147.py
'''
#通过推导式来输出
print("########################")
file_list2 = [filename for filename in os.listdir(path) if filename.endswith("py")]
for f in file_list2:
print(f, end="\t")
#任务.py 任务140.py 任务142.py 任务143.py 任务144.py 任务145 os模块.py 任务147.py
三、shutil模块和zipfile模块(拷贝和压缩)
主要用来做文件和文件夹的拷贝、移动、删除等,还可以做文件和文件夹的压缩、解压缩文件
os模块提供了对目录或文件的一般操作,shutil模块作为补充,提供了移动、复制、压缩、解压等操作,这些都是os模块不具有的
import shutil
import zipfile
#shutil.copyfile("1", "1_copy") #把文件1拷贝到1_copy里面
#shutil.copytree("movie/港台", "电影")
#在这里呢,movie和港台都没拷贝,拷贝的是港台下面的子目录和子文件
#shutil.copytree("movie/港台", "电影1", ignore= shutil.ignore_patterns("*.txt")) #在最后写明了所有后缀为.txt的文件都不拷贝
########################压缩、解压##############################
shutil.make_archive("电影/gg", "zip", "movie/港台")
#把movie文件里面的港台文件压缩成zip格式,放在电影下面的gg文件里
#查看的之后,右键压缩文件选择”show in explor“
z = zipfile.ZipFile("a.zip", "w") #生成zipfile生成器,写入文件名,没有指定位置时,默认在工作空间里,以写入的方式打开
z.write("1", "1_copy") #把1和1_copy这两个文件写进去
z.close() #最后要记得关闭哦
#可以指定路径
#z1 = zipfile.ZipFile("d:/a.zip", "w")
#z1.write("1")
#z1.write("1_copy")
#z.close() #最后要记得关闭哦
z2 = zipfile.ZipFile("d:/a.zip", "r") #把压缩文件读入
z2.extractall("电影") #将所有的文件都压缩到电影里面
z2.close()
四、递归算法
1、递归算法
包括两部分:
(1)定义递归头:解答什么时候不用调用自身方法,如果没有头,将会陷入死循环;
(2)递归体:什么时候需要调用自身方法
def a():
print("a")
b()
#在a方法里面调用b方法是可以的
#在a方法里面调用自己会死循环
def b():
print("b")
a()
当每个栈的值向上返回时,栈就结束了使命,关闭了。
num = 1
def a():
global num #在函数中想要改变全局变量的值,必须声明一下才可以呢!
num += 1
print("a")
if num < 5:
a()
#else:
#break
#break/continue 只适用于while、for这样的循环
a()
#小练习,计算n的阶乘
def f(n):
if n == 1:
return n #这一步最关键了,是关闭栈的时候返回的那个值
else:
return n * f(n-1)
print(f(5))
#120
2、递归算法原理——目录树结构展示
import os
def getAllFiles(path):
childFiles = os.listdir(path) #把传递路径的文件的目录收集起来
for file in childFiles:
filepath = os.path.join(path, file)
print(filepath)
getAllFiles("test.os")
#test.os\movie
#test.os\任务148.py
#此时,文件test.os里面确实有两个文件夹
#但我们相把所有的文件内容都打印出来,就需要递归处理了
import os
def getAllFiles(path):
childFiles = os.listdir(path) #把传递路径的文件的目录收集起来
for file in childFiles:
filepath = os.path.join(path, file)
if os.path.isdir(filepath):
getAllFiles(filepath)
print(filepath)
getAllFiles("test.os")
'''
test.os\movie
test.os\任务148.py
test.os\movie\日本
test.os\movie\欧美
test.os\movie\港台\周星驰\功夫.mp4
test.os\movie\港台\周星驰
test.os\movie\港台
test.os\movie
test.os\任务148.py
'''
#加缩进!
import os
def getAllFiles(path, level):
childFiles = os.listdir(path) #把传递路径的文件的目录收集起来
for file in childFiles:
filepath = os.path.join(path, file)
if os.path.isdir(filepath):
getAllFiles(filepath, level+1)
print("\t" * level + filepath)
#"\t"是制表符,level等于0 的时候不缩进,每增加1,就缩进4个字节
getAllFiles("test.os", 0)
'''
test.os\movie
test.os\任务148.py
test.os\movie\日本
test.os\movie\欧美
test.os\movie\港台\周星驰\功夫.mp4
test.os\movie\港台\周星驰
test.os\movie\港台
test.os\movie
test.os\任务148.py
'''
allfiles = []
def getAllFiles(path, level):
childFiles = os.listdir(path) #把传递路径的文件的目录收集起来
for file in childFiles:
filepath = os.path.join(path, file)
if os.path.isdir(filepath):
getAllFiles(filepath, level+1)
allfiles.append("\t" * level + filepath)
getAllFiles("test.os", 0)
for f in reversed(allfiles): #倒序
print(f)
#同样可以实现跟上面代码一样的效果呢
'''
test.os\movie
test.os\任务148.py
test.os\任务148.py
test.os\movie
test.os\movie\港台
test.os\movie\港台\周星驰
test.os\movie\港台\周星驰\功夫.mp4
test.os\movie\欧美
test.os\movie\日本
'''