educoder平台课-Python程序设计-8.文件
课程链接:头歌实践教学平台
8.1 文件的打开与关闭
不论是文本文件还是二进制文件,文件进行写入或读取操作,一般都可以分为以下三步:
(1)打开文件并创建文件对象;open()
(2)通过文件对象对文件中的内容进行读取和写入等操作;
(3)关闭并保存文件内容。close()
fr = open(file, mode='r', encoding=None) # fr为变量名,是用户为文件对象所命名字 fr.close() # 关闭所创建的文件对象,fr为文件对象名
内容管理器由关键字“with”和“as”联合启动,将文件打开操作置于内容管理器中,不需要用f.close()显式的关闭文件
with open(file, mode='r', encoding=None) as fr: # fr为变量名,是用户为文件对象所命名字pass # 在缩进区域写对文件对象进行操作的语句
file 参数是一个带路径的文件名:
绝对路径:
从根目录开始,如'c:\temp\temp.txt'
相对路径:
相对当前文件位置的路径,如:
./temp.txt (.表示当前目录,..表示上级目录)
../data/temp.txt (..表示上级目录,../data/表示当前文件上级目录的子目录,即当前文件同级的子目录)
当打开的文件与当前程序文件在同一路径下时,不需要写路径,一般建议使用相对路径。
使用绝对路径时,若反斜杠与后面字符可构成转义字符时,需使用两个反斜杠表示。
'c:\temp\next.txt'
print('c:\temp\next.txt')
# 输出结果为:
# c: emp
# ext.txt# “\t”是转义字符,所以需要写成
'c:\\temp\\next.txt'
print('c:\\temp\\next.txt') # 输出结果为: c:\temp\next.txt
或是在路径字符串前面加“r”,明确告诉编译器这个字符串是个原生字符串,不要转义,从而避免解析错误。
print('c:\temp\next.txt')
# 输出结果为:
# c: emp
# ext.txt
# 前面加r构建原生字符串,不转义
print(r'c:\temp\next.txt') # 输出结果为: c:\temp\next.txt
mode 参数是可选参数,用于指定文件打开的方式和类型
该参数可以使用的符号包括:
'r'、'w'、'x'、'a'、'b'、't'、'+'
符号 | 含义 |
---|---|
'r' | 以只读模式打开文件(默认值) |
'w' | 以写数据模式打开文件,该文件已存在,先清除该文件中所有内容;该文件不存在,先创建该文件再打开。 |
'x' | 以创建文件写数据模式打开文件,该文件已存在,打开失败。 |
'a' | 以追加写数据模式打开文件,该文件已存在,新数据追加在现有数据之后;该文件不存在,先创建文件后在打开。 |
'b' | 以二进制模式打开文件处理数据 |
't' | 以文本模式打开文件处理数据(默认模式) |
'+' | 打开文件并允许更新,相当于增加读或写模式(与 'r'、'w' 或 'a' 组合使用,如 'r+'可读可写、'w+'可写可读、'a+'可追加写,可读) |
1. mode 参数缺省时使用默认值'r',以只读方式打开。
2. encoding 参数缺省时时使用当前操作系统默认编码类型(中文 windows10 一般默认 GBK 编码,Mac 和Linux等一般默认编码为UTF-8 编码) 用二进制对象返回文件内容时,encoding 参数不可用。
读取"What is New in Python3.11.txt"文件内容:
What is New in Python3.11.txt
new = open('/data/bigfiles/What is New in Python3,11.txt') # 以读模式打开文件,创建文件对象,命名为new print(new.read()) # 读文件为字符串输出 new.close() # 关闭文件对象
with open('/data/bigfiles/What is New in Python3,11.txt') as new: # 以读模式打开文件,创建文件对象,命名为newprint(new.read()) # 读文件为字符串输出# 退出缩进时自动关闭文件
读取并输出文件“9.1 出塞.txt”中的内容
9.1 出塞.txt
fr = open('/data/bigfiles/9,1 出塞.txt', 'r', encoding='utf-8') # 打开文件创建文件对象,命名为fr print(fr.read()) # 读文件为字符串输出 fr.close() # 关闭文件对象
fr = open('/data/bigfiles/9,1 出塞.txt', 'r', encoding='utf-8') # 打开文件创建文件对象,命名为fr for line in fr: # 对文件对象进行逐行遍历print(line) # 行末的换行符会输出一个空行 fr.close() # 关闭文件对象
fr = open('/data/bigfiles/9,1 出塞.txt', 'r', encoding='utf-8') # 打开文件创建文件对象,命名为fr for line in fr: # 对文件对象进行逐行遍历print(line.strip()) # line.strip()函数去掉行末的换行符,消除空行 fr.close() # 关闭文件对象
# 用上下文管理器实现,不需要显示关闭文件,避免异常with open('/data/bigfiles/9,1 出塞.txt','r',encoding = 'utf-8') as poem: # 打开文件创建文件对象,命名为poemprint(poem.read()) # 读文件为字符串输出
# 用上下文管理器实现,不需要显示关闭文件,避免异常with open('/data/bigfiles/9,1 出塞.txt','r',encoding = 'utf-8') as poem: # 打开文件创建文件对象,命名为poemfor line in poem: # 对文件对象进行逐行遍历print(line.strip()) # line.strip()函数去掉行末的换行符,消除空行
建议将读文件的代码定义为函数,以方便修改和维护代码:
def open_file(file): """接收表示文件名的字符串变量,打开文件,遍历读取文件并输出其内容"""with open(file,'r',encoding = 'utf-8') as poem: # 打开文件创建文件对象,命名为poemfor line in poem: # 对文件对象进行逐行遍历print(line.strip()) # line.strip()函数去掉行末的换行符,消除空行 if __name__ == '__main__':filename = '/data/bigfiles/9,1 出塞.txt' # 文件名定义变量,方便修改open_file(filename) # 调用函数读取并输出文件内容
What is New in Python3.11.txt
9.1 出塞.txt
8.2 文件读写操作
本节可能用到的文件:
data.tar
9.1 出塞.txt
Who Moved My Cheese.txt
百家姓.txt
出塞.txt
What is New in Python3.11.txt
文件读取方法
Python文件对象fr提供了三个读取数据的方法:
fr.read()
fr.readline()
fr.readlines()
方法 | 描述 |
---|---|
read(size) | 无参数或参数为-1时,读取全部文件内容为一个字符串;当参数size为大于或等于0的整数时,读取size个字符。 |
readline(size) | 无参数或参数为-1时,读取并返回文件对象中的一行数据,包括行末结尾标记'\n',字符串类型。当参数size为大于或等于0的整数时,从指针所在处向后最多读取当前行的前size个字符,当前行剩余字符少于size时,读取到行末。 |
readlines(hint) | 无参数时,读取文件全部数据,返回一个列表,列表中每个元素是文件对象中的一行数据,包括行末的换行符’\n’。 当参数hint为大于或等于0的整数时,返回文件从头到第hint个字符所在的行末。 |
seek(offset,whence) | 改变当前文件操作指针指针的位置,offset为指针偏移量,whence代表参照物,有三个取值:0文件开始、1当前位置、2文件结尾。在文本文件(模式字符串未使用b时打开的文件)中,只允许相对于文件开头搜索。 |
tell() | 返回文件指针当前的位置,返回值与编码有关。 |
在文件刚打开时,指针是指向文件内容的起始处,伴随着读写的进行指针一步一步往后移动。当指针移动到文件结尾后,再试图读取数据就没有返回值了。
如果期望重新读取文件中的数据,可使用seek(0) 将文件读取指针移动到文件开始的位置。
seek(0) # 将文件指针移动到文件开始位置
实例 9.1 输出文件内容
有一个utf-8编码的文本文件“出塞.txt”,内容如下:
出塞
秦时明月汉时关,万里长征人未还。
但使龙城飞将在,不教胡马度阴山。
编程读取文件的内容。
访问文件里的数据,必须先用 open() 函数打开文件,只读取文件,不修改文件内容时,读取模式参数 mode 的值可设为 ‘r’ 或缺省。encoding='utf-8' 参数表示以“utf-8”编码方式处理数据
9.1 出塞.txt
with open( '/data/bigfiles/9,1 出塞.txt','r',encoding = 'utf-8') as poem: # 打开文件创建文件对象,命名为poemprint(poem.read()) # 读文件为字符串输出for line in poem: # 指针在文件末尾,后面无数据,读到空字符串print(line.strip()) # 无输出
with open( '/data/bigfiles/9,1 出塞.txt','r',encoding = 'utf-8') as poem: # 打开文件创建文件对象,命名为poemprint(poem.read()) # 读文件为字符串输出poem.seek(0) # 将文件指针移动到文件开始位置for line in poem: # 指针在文件开头print(line.strip()) # 重新输出一次文件内容
read(size=-1)
从文本文件中读取并返回最多 size 个字符,返回的数据类型为字符串 size 为负值或值是 None 时,从当前位置一直读取到文件结束(End Of File,EOF) 读取的字符包括标点符号和空格、换行符等空白字符。
with open( '/data/bigfiles/9,1 出塞.txt','r',encoding = 'utf-8') as poem: # 打开文件创建文件对象,命名为poemprint([poem.read(20)]) # 读取前20个字符,放入列表中输出是为了能看到换行符print(poem.read()) # 输出剩余字符
readline(size=-1)
每次只读取一行数据,文件指针移动到下一行开始。 如果指定了 size ,将在当前行读取最多 size 个字符,本行剩余字符少于size时,读取到本行结束。
字符串末尾保留换行符(\n),空行使用 '\n' 表示,该字符串只包含一个换行符。
with open( '/data/bigfiles/9,1 出塞.txt','r',encoding = 'utf-8') as poem: # 打开文件创建文件对象,命名为poemprint([poem.read(11)]) # ['出塞\n秦时明月汉时关,'],字符串末尾保留换行符print(poem.readline(10)) # 万里长征人未还。
为了更好的理解这个命令的用法,我们使用以下诗句:
出塞王昌龄(唐)
秦时明月汉时关,万里长征人未还。 但使龙城飞将在,不教胡马度阴山。
为了观察方便,将空格用中文数字代替:
一二三四五六出塞 一二三四五六七八王昌龄(唐) 秦时明月汉时关,万里长征人未还。 但使龙城飞将在,不教胡马度阴山。
file = '/data/bigfiles/出塞.txt' with open(file, 'r', encoding='utf-8') as poem: # 打开文件创建文件对象,命名为poemfor i in range(1, 12): print(i, [poem.readline(i)], poem.tell()) # 从当前行可读数据中读取前i个字符,指针后移
poem.tell()获取当前指针位置,从输出结果看,每次只读取当前行指针位置后面的若干个字符,最多不超过当前行。
这种方式让返回值清晰明确;只要 f.readline() 返回空字符串,就表示已经到达了文件末尾。
with open( '/data/bigfiles/9,1 出塞.txt','r',encoding = 'utf-8') as poem: # 打开文件创建文件对象,命名为poemwhile txt := poem.readline(): # 逐行读文件,直至文件结束print(txt.strip()) # 去除行末的换行符后输出当前读到的字符串
with open( '/data/bigfiles/9,1 出塞.txt','r',encoding = 'utf-8') as poem: # 打开文件创建文件对象,命名为poemprint(poem.readlines()) # 输出全部内容放入列表
with open( '/data/bigfiles/9,1 出塞.txt','r',encoding = 'utf-8') as poem: # 打开文件创建文件对象,命名为poemprint(poem.readlines(4)) # 输出到第4个字符"秦"所在的行的数据, ['出塞\n', '秦时明月汉时关,万里长征人未还。\n']
实例 9.2 提取文件中的英文
Who Moved My Cheese.txt
def read_file(file):"""接收文件名为参数,将文件中的内容读为字符串,过滤掉中文(中文字符及全角符号Unicode编码都大于256),返回字符串 """with open(file, 'r', encoding='utf-8') as novel:txt = novel.read() # 读取文件全部内容为字符串english_txt = ''for x in txt:if ord(x) < 256:english_txt = english_txt + x # 过滤掉中文,拼接为字符串return english_txt # 返回英文文本if __name__ == '__main__':filename = '/data/bigfiles/Who Moved My Cheese.txt'print(read_file(filename))
def read_file(file):"""接收文件名为参数,将文件中的内容读为字符串,过滤掉中文(中文字符及全角符号Unicode编码都大于256),返回字符串 """with open(file, 'r', encoding='utf-8') as novel:txt = novel.read() # 读取文件全部内容为字符串english_txt = ''.join([x for x in txt if ord(x) < 256]) # 过滤掉中文,拼接为字符串return english_txt # 返回英文文本if __name__ == '__main__':filename = '/data/bigfiles/Who Moved My Cheese.txt'print(read_file(filename))
实例 9.3 读百家姓获得姓的列表
提示: 百家姓前51行为单姓,51行以后为复姓,需要分别处理。 每行读取为字符串,去除换行符、逗号和句号拼接为一个字符串,再用list()转列表,每个字为一个元素 51行以后拼接为一个字符串,每次取两个字加入列表
def read_txt(): # 根据性别生成一个姓名"""无参数,读百家姓文件,将单字姓和复姓拆分,返回以姓为元素的列表"""with open('/data/bigfiles/百家姓.txt', 'r', encoding='utf-8') as data:# 替换掉换行符、逗号和句号,每行转为一个字符串,得到列表last_ls = [line.strip().replace(',', '').replace('。', '') for line in data]# print(last_ls) # ['赵钱孙李周吴郑王', '冯陈褚卫蒋沈韩杨', ...]single = list(''.join(last_ls[:51])) # 前51行为单字姓,拼接为一个字符串转列表# print(single) # ['赵', '钱', '孙', '李', '周', '吴', '郑', '王',...]double_txt = ''.join(last_ls[51:]) # 51行后为复姓,拼接为一个字符串double = [] # 创建空列表for i in range(0, len(double_txt), 2): # 遍历字符串序号,步长为2double.append(double_txt[i: i + 2]) # 当前序号向后切2个字符,加入到列表# double = [double_txt[i: i + 2] for i in range(0, len(double_txt), 2)] # 列表推导式方法# print(double) # ['万俟', '司马', '上官', '欧阳', '夏侯', '诸葛', '闻人', '东方', ...]lastname = single + double # 单字姓列表与复姓列表拼接为一个列表return lastname # 返回百家姓中所有姓的列表if __name__ == '__main__':family_names = read_txt() # 调用函数将文件读为列表print(family_names) # 输出
应用实例
有一个10G的日志文件需要读取后处理,某程序员的解决方案是:
lines = open('10g.log').readlines()
结果是内存炸了!读个日志把服务器读崩了!
其原因就是一次性把整个读取到内存,导致内存占用过高。
更好的方法是使用迭代机制,逐行读取,可以每1000行处理一次,这样内存点用约1M就可以解决问题了。
这样操作内存效率高,迭代器按需加载,1GB 文件只占单行内存,无需预读即可动态控制批次大小
with open('10g.log') as fr: # 打开文件,创建名为fr的文件对象batch = [] # 创建空列表for i, line in enumerate(fr, 1): # 读取时从1开始计数,i为读取的行数batch.append(line.strip()) # 当前行去除开头结尾的空白字符后加入到列表中if i % 1000 == 0: # 每1000行处理一次process(batch) # 调用处理函数处理列表中的1000条数据batch = [] # 清空列表,等待装入新数据if batch: # 文件读取完,若最后剩余不足1000行时,处理剩余行process(batch) # 处理列表中剩余数据
文件写入方法
进行文件的写入操作,使用 open() 函数时,要将 mode 参数设置为 'w'、'x'、'a'等具有写权限的模式。
或用“r+”为读模式打开的文件增加写权限。
注意:
使用“r+”模式时文件处于改写状态,新写入的数据会覆盖原文件起始位置相同字符数量的数据。
写入数据的方法: write() writelines() writelines()方法不会自动在每一个元素后面增加换行,只是将列表内容直接输出,所以在构造列表时,在需要换行的位置加入一个' \n',以控制写入时换行。这两种方法可将字符串和列表中的内容写入到文件中永久保存。
方法 | 描述 |
---|---|
write(b) | 将给定的字符串或字节流对象写入文件 |
writelines(lines) | 将一个元素全为字符串的列表写入文件。构造列表时,在需要换行的位置加入换行符' \n',以控制写入时换行。 |
实例 9.4 追加写文件
将字符串 '姓名,C语言,Java,Python,C#\n罗明,95,96,85,63\n朱佳,75,93,66,85\n' 写入到当前路径下的'score.txt'中,再把列表 ['李思,86,76,96,93\n郑君,88,98,76,90\n'] 中的数据追加到文件'score.txt'中,读文件查看写入是否正确。
def write_str(s, filename):"""接收要写入的字符串和文件名为参数,将字符串追加写入到文件现在数据末尾"""with open(filename, 'w', encoding='utf-8') as f:f.write(s) # 将字符串s写入文件def write_list(ls, filename):"""接收要写入的列表和文件名为参数,将列表中的字符串追加写入到文件现在数据末尾"""with open(filename, 'a', encoding='utf-8') as f:f.writelines(ls) # 将列表ls写入文件,附加到后面def read_file(filename):"""接收表示文件名的字符串为参数,读文件,以字符串形式返回"""with open(filename, 'r', encoding='utf-8') as f:return f.read() # 返回字符串形式的文件内容if __name__ == '__main__':file = 'score.txt' # 定义文件名变量,方便程序扩展和修改score_str = '姓名,C语言,Java,Python,C#\n罗明,95,96,85,63\n朱佳,75,93,66,85\n'score_lst = ['李思,86,76,96,93\n郑君,88,98,76,90\n']write_str(score_str, file) # 传递要写入的字符串和文件名为参数write_list(score_lst, file) # 传递要写入的列表和文件名为参数print(read_file(file)) # 读文件,查看写入是否成功
9.1 出塞.txt
Who Moved My Cheese.txt
百家姓.txt
8.3 文件的应用
csv文件
CSV是文本文档,所以对文本进行读写的方法都适用于CSV格式文件的数据处理。而CSV格式的文件里的数据基本上都是由行和列构成的二维数据,可以使用列表嵌套的方法对其进行处理。
实例 9.5 读文件处理文件中的数据
文件5.7 score.csv 中数据如下,读取其中的数据并进行处理。
姓名,C语言,Java,Python,C#,C++ 罗明,95,96,85,63,91 朱佳,75,93,66,85,88 李思,86,76,96,93,67 郑君,88,98,76,90,89 王雪,99,96,91,88,86
按要求完成以下操作: 1. 请读取文件中的数据,每行数据根据逗号切分为列表,输出二维列表。 2. 计算每位同学的总分附加到列表中各门课程成绩后面 3. 根据每名同学的总分进行降序排序输出 4. 将排序后的结果写入到新文件 “9.2 score_total.csv” 中
# 读文件中的数据为二维列表 score_ls = [] # 创建空列表 with open('/data/bigfiles/5,7 score.csv','r',encoding='utf-8') as fr:for line in fr: # 遍历文件对象score_ls.append(line.strip().split(',')) # 文件每行切分为一个列表,split()参数根据文件中的分隔符确定 print(score_ls)
定义为函数,用列表推导式实现更简洁,类似问题只修改文件名和切分时使用的分隔符即可重用此代码。
def read_file(filename):"""接收文件名为参数,读取文件中的数据为二维列表,返回二维列表"""with open(filename, 'r', encoding='utf-8') as fr:score_ls = [x.strip().split(',') for x in fr]return score_lsif __name__ == '__main__':score_lst = read_file('/data/bigfiles/5,7 score.csv')print(score_lst)
为每位同学增加总成绩,可以将列表序号为0的元素score[0]拼接上['总分'],对剩余部分列表 score[1:] 进行遍历,每次得到一位同学的列表 x ,切片 x[1:] 为各门课的成绩,用map()函数将每个元素都 映射为整数,再用 sum() 函数对其进行求和并附加到列表中。
def read_file(filename):"""接收文件名为参数,读取文件中的数据为二维列表,返回二维列表"""with open(filename, 'r', encoding='utf-8') as fr:score_ls = [x.strip().split(',') for x in fr]return score_lsdef add_total(score_ls):"""接收二维列表,增加总分,返回新的二维列表"""title = score_ls[0] + ['总分'] # 列表拼接,一维列表score_total = [title] # 创建新列表,首元素为原列表标题行增加平均成绩for x in score_ls[1:]: # 略过标题行进行遍历total = sum(map(int, x[1:])) # 切取成绩部分映射为整数,计算总成绩score_total.append(x + [str(total)]) # 每个列表拼接字符型平均成绩return score_totalif __name__ == '__main__':score_lst = read_file('/data/bigfiles/5,7 score.csv')print(add_total(score_lst))
将增加了总成绩的列表数据写入到文件中
def read_file(filename):"""接收文件名为参数,读取文件中的数据为二维列表,返回二维列表"""with open(filename, 'r', encoding='utf-8') as fr:score_ls = [x.strip().split(',') for x in fr]return score_lsdef add_total(score_ls):"""接收二维列表,增加总分,返回新的二维列表"""title = score_ls[0] + ['总分'] # 列表拼接,一维列表score_total = [title] # 创建新列表,首元素为原列表标题行增加平均成绩for x in score_ls[1:]: # 略过标题行进行遍历total = sum(map(int, x[1:])) # 切取成绩部分映射为整数,计算总成绩score_total.append(x + [str(total)]) # 每个列表拼接字符型平均成绩return score_totaldef write_file(score_total, filename):"""接收成绩二维列表和写入文件名的字符串,将二维列表中的数据分行写入文件,每个列表中的数据写为一行,用逗号分隔无返回值"""with open(filename, 'w', encoding='utf-8') as fw: # 写模式打开文件for line in score_total: # 遍历二维列表fw.write(','.join(line) + '\n') # 子列表元素用逗号拼接为字符串加换行符if __name__ == '__main__':score_lst = read_file('/data/bigfiles/5,7 score.csv')score_total_ls = add_total(score_lst)write_file(score_total_ls, 'score_total.csv')print(read_file('score_total.csv'))
# 获取并输出python课程的成绩的列表
def read_file(filename):"""接收文件名为参数,读取文件中的数据为二维列表,返回二维列表"""with open(filename, 'r', encoding='utf-8') as fr:score_ls = [x.strip().split(',') for x in fr]return score_lsdef get_python_avg(score_ls):"""接收二维列表,返回全部学生python的平均成绩"""# 补充你的代码python = [int(x[3]) for x in score_ls[1:]]return sum(python) / len(python)if __name__ == '__main__':score_lst = read_file('/data/bigfiles/5,7 score.csv')print(get_python_avg(score_lst))
with open(filename, encoding='utf-8') as f:
'''with open(filename, encoding='utf-8') as f::这行代码使用with语句来打开文件。with语句在Python中用于资源管理,它确保文件在操作完成后会被正确关闭,即使在操作过程中发生异常也是如此。open(filename, encoding='utf-8'):打开指定路径的文件,filename是文件的路径。encoding='utf-8'指定了文件的编码格式为UTF-8,这通常用于确保可以正确读取和处理包含非ASCII字符的文本。as f:将打开的文件对象赋值给变量f,以便后续操作。'''return [x.strip().split(',') for x in f]
'''return [x.strip().split(',') for x in f]:这行代码使用列表推导式来读取文件内容并将其转换为一个二维列表。for x in f:for循环遍历文件对象f中的每一行。f是一个可迭代对象,每次迭代返回文件的一行。x.strip():strip()方法用于去除字符串x(即文件的一行)开头和结尾的空白字符(包括换行符\n)。x.strip().split(','):split(',')方法将字符串x按逗号分隔,返回一个列表。因为CSV文件中的数据通常是用逗号分隔的,所以这个操作将一行数据拆分为多个字段。[x.strip().split(',') for x in f]:整个列表推导式将文件中的每一行处理为一个列表,最终将这些列表组合成一个二维列表,其中每个子列表代表文件中的一行数据。总结来说,这段代码打开一个文件,读取每一行,去除每行的空白字符,然后按逗号分隔每行,最终返回一个二维列表,其中每个子列表代表文件中的一行数据。
'''
JSON文件
JSON的编码过程是将一个Python对象转为JSON格式数据,
主要使用json.dumps(obj)和json.dump(obj,fp)两个方法。
json.dumps(obj, *, ensure_ascii=True, indent=None, sort_keys=False)
json.dump(obj, fp, *, ensure_ascii=True, indent=None, sort_keys=False)
方法 | 描述 |
---|---|
json.dumps(obj) | 将Python 数据类型obj对象编码成JSON数据,写入内存。 |
json.dump(obj,fp) | 将Python 数据类型obj对象编码成JSON数据,写入磁盘文件对象fp中。 |
json 中默认ensure_ascii=True, 会将中文等非ASCII 字符转为unicode 编码(形如\uXXXX),设置ensure_ascii=False 可以禁止JSON 将中文转为unicode 编码,保持中文原样输出。
Python中的字典数据转为JSON 默认不排序。可设置sort_keys=True使转换结果按照字典升序排序(a-z)。
indent 参数可用来对JSON 数据进行格式化输出,默认值为None,不做格式化处理,可设一个大于0 的整数表示缩进量,例如indent=4。输出的数据被格式化之后,变得可读性更好。
JSON的解码过程是将JSON格式数据转为Python对象,Python 的原始类型与JSON类型会相互转换。
主要使用json.loads(s)和json.load(fp)两个方法。
方法 | 描述 |
---|---|
json.loads(s) | 将字符串s中的JSON数据解码为Python 数据类型,其他格式数据会转为unicode格式。 |
json.load(fp) | 将磁盘文件对象fp中的JSON数据解码为Python 数据类型,其他格式数据会转为unicode格式。 |
将csv文件"成绩分析综合.csv"转为json文件
import jsondef read_csv(filename):"""读文件到二维列表,返回二维列表"""with open(filename, "r", encoding='utf-8') as f:return [x.strip().split(',') for x in f]def to_json(score_ls):"""将二维列表标题行的元素与子列表中的元素一一组合,禁止JSON 将中文转为unicode 编码,保持中文原样输出。对JSON 数据进行格式化输出,缩进4个字符,返回json格式数据"""score_dic = []for i in range(1, len(score_ls)):score_dic.append(dict(zip(score_ls[0], score_ls[i])))return json.dumps(score_dic, ensure_ascii=False, indent=4)def write_to_json(score_ls):"""将二维列表标题行的元素与子列表中的元素一一组合,禁止JSON 将中文转为unicode 编码,保持中文原样输出。对JSON 数据进行格式化输出,缩进4个字符,写入json格式文件"""score_dic = []for i in range(1, len(score_ls)):score_dic.append(dict(zip(score_ls[0], score_ls[i])))with open('成绩分析综合.json','w',encoding='utf-8') as score_json:json.dump(score_dic,score_json, ensure_ascii=False, indent=4)def read_json_to_ls(filename):"""读json文件,返回元素为字典类型的列表"""with open(filename, "r", encoding='utf8') as f:score_dic_ls = json.load(f)return score_dic_lsif __name__ == '__main__':score_lst = read_csv('/data/bigfiles/成绩分析综合.csv')# print(to_json(score_lst))write_to_json(score_lst)print(read_json_to_ls('成绩分析综合.json'))
def read_json(filename):"""读json文件,以字符串形式输出,查看写入文件的格式"""with open(filename, "r", encoding='utf8') as f:print(f.read())if __name__ == '__main__':read_json('成绩分析综合.json')
借用eval()实现json转csv
eval()可以将字符串转为python数据类型,所以可以先用read()将json文件内容读取为字符串,再用eval()转为列表,再转csv文件
with open('成绩分析综合.json',encoding='utf-8') as fr:txt = fr.read() # txt为字符串txt_py = eval(txt) # txt_py为元素为字典的列表 title = list(txt_py[0].keys()) # title为标题列表 score = [list(i.values()) for i in txt_py] # score为值的列表 score_ls = [title]+score # score_ls为标题+值的列表with open('成绩分析综合.csv','w',encoding='utf-8') as fw:for lst in score_ls: # 遍历列表fw.write(','.join(lst)+'\n') # 将列表用逗号拼接为字符串并写入文件
文件和目录访问
pathlib --- 面向对象的文件系统路径
该模块提供表示文件系统路径的类,其语义适用于不同的操作系统。路径类被分为提供纯计算操作而没有 I/O 的 纯路径,以及从纯路径继承而来但提供 I/O 操作的 具体路径。
pathlib 是 Python 标准库中最近添加的更大的内容之一, 自 Python 3.4 以来,它一直是标准库的一部分,pathlib 只是替代 os.path 而不是整个 os 模块。pathlib 与旧的 os.path 相比具有许多优点, os 模块以原始字符串格式表示路径,pathlib 使用面向对象的样式,这使得它更具可读性和编写自然:
导入主类:
from pathlib import Path
列出子目录:
from pathlib import Path
p = Path('.')
print([x for x in p.iterdir() if x.is_dir()])
列出当前目录树下的所有 Python 源代码文件:
from pathlib import Path
p = Path('.')
print(list(p.glob('**/*.py')))
os库常用方法
方法 | 描述 |
---|---|
os.getcwd() | 获取当前工作路径 |
os.chdir(path) | 将当前工作路径修改为path,如os.chdir(r'c:\Users') |
os.walk(path) | 返回类型为生成器,包含数据为若干包含文件和文件夹名的元组数据 |
os.listdir(path) | 以列表形式返回path路径下的所有文件名,不包括子路径中的文件名 |
os.mkdir(pathname) | 新建一个名为pathname的文件夹 |
os.rmdir(pathname) | 删除空文件夹pathname,文件夹不为空则报OSError错误 |
os.remove(filename) | 删除文件 filename,文件不存在则报错 |
os.path.isfile(path) | 返回path是否是常规文件,是返回True,否则返回False |
os.path.isdir(path) | 返回path是否是目录,是返回True,否则返回False |
os.path.getsize(file) | 文件file存在,返回其大小(byte为单位),不存在则报错 |
os.path.exist(name) | 判断name文件夹或文件是否存在,存在返回True,否则返回False |
# getcwd() 获取当前工作目录import osresult = os.getcwd() print(result)
import osresult = os.listdir('/data/workspace/') print(result)
实例9.6 批量改文件名
重要:请运行下面单元的代码以获取实验数据文件!!!
!tar -xvf /data/bigfiles/1cd06ad9-cef1-4267-b6fc-fbce214a089f.tar
import osdef read_to_dic():"""读股票代码文件,返回以股票代码为键,以股票名为值的字典"""stock_dic = {}with open('./stock_data/stock_basic.csv', 'r', encoding='utf-8') as stock:stock.readline() # 读取标题行不用,跳过for line in stock:code, x, stock_name = line.strip().split(',')[:3] # x 数据无用,跳过stock_dic[code] = stock_name # 股票代码为键,股票名为值# print(stock_dic)return stock_dicdef re_name(file_ls):"""遍历列表中文件名,修改对应文件名为股票代码对应的股票名"""stock = {'SZ': '_深圳', 'SH': '_上海', 'BJ': '_北京'} # 构建交易市场字典for stock_code in file_ls: #stock_name = stock_dict.get(stock_code[:-4]) + stock.get(stock_code[-6:-4])print(stock_name)os.rename(path + stock_code, new_path + stock_name + '.csv')if __name__ == '__main__':path = './stock_data/old/' # 当前路径下的stock文件夹中有类似600000.csv的多个文件new_path = './stock_data/new/' # 当前路径下的空文件夹file_list = os.listdir(path) # 获取文件夹中的文件名列表print(file_list) # ['600000.csv', '600004.csv', '600006.csv',...'沪市股票top300.csv']stock_dict = read_to_dic() # 获取代码与股票名的字典re_name(file_list)file_list = os.listdir(new_path) # 获取new_path文件夹中的文件名列表print(file_list) # ['600000.csv', '600004.csv', '600006.csv',...'沪市股票top300.csv']
输出:
[] ['万通液压_北京.csv', '中国通号_上海.csv', '中微公司_上海.csv', '交控科技_上海.csv', '仙琚制药_深圳.csv', '光峰科技_上海.csv', '凯添燃气_北京.csv', '国义招标_北京.csv', '天臣医疗_上海.csv', '容百科技_上海.csv', '富安娜_深圳.csv', '得利斯_深圳.csv', '新光光电_上海.csv', '新安洁_北京.csv', '新朋股份_深圳.csv', '杭可科技_上海.csv', '森萱医药_北京.csv', '永太科技_深圳.csv', '洪涛股份_深圳.csv', '海希通讯_北京.csv', '润农节水_北京.csv', '澜起科技_上海.csv', '皇氏集团_深圳.csv', '皖通科技_深圳.csv', '福光股份_上海.csv', '罗普斯金_深圳.csv', '艾融软件_北京.csv', '英威腾_深圳.csv', '齐鲁华信_北京.csv', '龙竹科技_北京.csv']
import osnew_path = './stock_data/new/' # 当前路径下的空文件夹 file_list = os.listdir(new_path) # 获取new_path文件夹中的文件名列表 print(file_list) # ['600000.csv', '600004.csv', '600006.csv',...'沪市股票top300.csv']
输出:
['万通液压_北京.csv', '中国通号_上海.csv', '中微公司_上海.csv', '交控科技_上海.csv', '仙琚制药_深圳.csv', '光峰科技_上海.csv', '凯添燃气_北京.csv', '国义招标_北京.csv', '天臣医疗_上海.csv', '容百科技_上海.csv', '富安娜_深圳.csv', '得利斯_深圳.csv', '新光光电_上海.csv', '新安洁_北京.csv', '新朋股份_深圳.csv', '杭可科技_上海.csv', '森萱医药_北京.csv', '永太科技_深圳.csv', '洪涛股份_深圳.csv', '海希通讯_北京.csv', '润农节水_北京.csv', '澜起科技_上海.csv', '皇氏集团_深圳.csv', '皖通科技_深圳.csv', '福光股份_上海.csv', '罗普斯金_深圳.csv', '艾融软件_北京.csv', '英威腾_深圳.csv', '齐鲁华信_北京.csv', '龙竹科技_北京.csv']
5.7 score.csv
成绩分析综合.csv