要点:Python能够以文本和二进制两种方式处理文件
文件是一个存储在辅助存储器上的数据序列,可以包含任何数据内容。概念上,文件是数据的集合和抽象,类似地,函数是程序的集合和抽象。用文件形式组织和表达数据更有效也更为灵活。文件包括两种类型:文本文件和二进制文件。
文本文件:一般由单一特定编码的字符组成,如UTF-8编码,内容容易统一展示和阅读。大部分文本文件都可以通过文本编辑软件或文字处理软件创建、修改和阅读。由于文本文件存在编码,因此它也可以被看作是存储在磁盘上的长字符串,例如一个txt格式的文本文件。
二进制文件:直接由比特0和比特1组成,没有统一字符编码,文件内部数据的组织格式与文件用途有关。二进制是信息按照非字符但特定格式形成的文件,例如png格式的图片文件、avi格式的视频文件。
区别:二进制文件和文本文件最主要的区别在于是否有统一的字符编码。二进制文件由于没有统一字符编码,只能当作字节流,而不能看作是字符串。
例:
首先用文本编辑器生成一个包含“中国是个伟大的国家!”的txt格式文本文件,命名为7.1.txt。分别用文本文件方式和二进制文件方式读入,并打印输出效果代码如下:
textFile = open("7.1.txt","rt",encoding='utf8') # t表示文本文件方式 rt:文本只读模式,读入程序算哦在目录中7.1.txt文件 或 textfile = open('7.1.txt') 有时出现汉字显示不出来时使用encoding可不用
print(textFile.readline())
textFile.close()
binFile = open("7.1.txt","rb") # b 表示二进制文件方式
print(binFile.readline())
binFile.close()
输出结果:
中国是一个伟大的国家!
b'\xe4\xb8\xad\xe5\x9b\xbd\xe6\x98\xaf\xe4\xb8\x80\xe4\xb8\xaa\xe4\xbc\x9f\xe5\xa4\xa7\xe7\x9a\x84\xe5\x9b\xbd\xe5\xae\xb6\xef\xbc\x81'
采用文本方式读入文件,文件经过编码形成字串符,打印出有含义的字符
采用二进制方式打开文件,文件被解析为字节(Byte)流。由于存在编码,字串符中的一个字符由两个字节表示。
Python对文本文件和二进制文件采用统一的操作步骤,即“打开—操作—关闭”。即使用文件之前,必须先打开文件,然后进行引读、写、添加等操作。
Python通过解释器内置的open()函数打开一个文件,并实现该文件与一个程序变量的关联,open()函数格式如下:
<变量名>=open(<文件名>,<打开模式>)
文件名可以是文件的实际名字,也可以是包含完整路径的名字。
打开模式用于控制使用何种方式打开文件。
或:
open(name[,mode,buffering,encoding])
name:必须提供的参数,文件的路径
f=open("d:\\1.txt")
f=open("d:/1.txt")
f=open("1.txt") # 当前目录下
只提供给open函数一个参数“name”,将范围一个只读的文件对象
mode:打开的模式
buffering:是否缓冲
encoding:编码模式
open()函数提供7种基本的打开模式
文件的打开模式 | 含义 |
---|---|
‘r’ | 只读模式,如果文件不存在,返回异常FileNotFoundError,默认值 |
‘w‘ | 覆盖写模式,文件不存在则创建,存在则完全覆 |
’x‘ | 创建写模式,文件不存在则创建,存在则返回异常值FileNotFoundError |
’a‘ | 追加写模式,文件不存在则创建,存在则在文件最后追加内容 |
’b‘ | 二进制文件模式 |
’t‘ | 文本文件模式,默认值 |
’+‘ | 与r/w/x/a一同使用,在原功能基础上增加同时读写功能 |
打开模式使用字符串方式表示,根据字符串定义,单引号或者双引号均可。上述打开模式中,’r‘、’w‘、’x‘、’a‘和’b‘、’t‘、’+‘组合使用,形成既表达读写又表达文件模式的方式。
例如,open()函数默认采用’rt‘(文本只读)模式。
读取一个二进制文件,如一张图片、一段视频或一段音乐,需要使用文件打开模式’rb‘。
例如,打开一个名为"music.mp3"的音频文件:
binfile = open('music.mp3','rb')
文件使用结束后要用close()方法关闭,释放文件的使用授权,该方法的使用方式如下:
<变量名>.close()
属性 | 含义 |
---|---|
closed | 用于判断文件是否关闭,若文件处于打开状体,则返回False |
mode | 返回文件的打开模式 |
name | 返回文件的名称 |
>>> f = open("1.txt") # f是一个文件的对象
>>> f.closed
False
>>> f.mode
'r'
>>> f.name
'1.txt'
当文件以文本文件方式打开时,读写按照字符串方式,采用当前计算机使用的编码或指定编码;
当文件以二进制文件方式打开时,读写按照字节流方式。
Python提供4个常用的文件内容读取方法(文件打开模式含有“r”“+”):
操作方法 | 含义 |
---|---|
.readall() | 读取整个文件内容,返回一个字符串或字节流* |
.read(size=-1) | 从文件中读入整个文件内容,如果给出参数,读入前size长度的字符串或字节流 |
.readline(size=-1) | 从文件中读入一行内容,如果给出参数,读入该行前size长度的字符串或字节流 |
.readlines(hint=-1) | 从文件中读入所有行,以每行为元素形成一个列表,如果给出参数,读入hint行 |
*:字符串或字节流取决于文件打开模式,如果是文本方式打开,返回字符串;否则返回字节流。下同。
>>> f = open("fy.txt","r")
>>> f.read(3)
'1.T'
>>> f.read()
"he China Manned Space Agency said the flight successfully verified \n2.the overall design and technologies of the new rocket and also marked\n3.the beginning of the third stage in China's manned space program, \n4.which aims to put a manned space station into orbit."
>>> f.close()
>>> f = open("fy.txt")
>>> f.readline(3)
'1.T'
>>> f.readline()
'he China Manned Space Agency said the flight successfully verified \n'
>>> f.close()
>>> f = open("fy.txt","r")
>>> f.readlines()
['1.The China Manned Space Agency said the flight successfully verified \n', '2.the overall design and technologies of the new rocket and also marked\n', "3.the beginning of the third stage in China's manned space program, \n", '4.which aims to put a manned space station into orbit.']
例:文本文件逐行打印
用户输入文件路径,以文本文件 方式读入文件内容并逐行打印,代码如下:
fname = input("请输入要打开的文件:") # 提示用户输入一个文件名
fo = open(fname, "r") # 打开文件并赋值给文件对象变量fo
for line in fo.readlines(): # 文件的全部内容通过fo.readline()方法读入到一个列表中,
print(line) # 列表的每个元素是文件一行的内容,然后通过for-in方式历遍列表,处理每行内容
fo.close()
当读入文件非常大时,一次性将内容读取到列表中会占很多内存,影响程序执行速度。一个合理的方法时逐行读入内容到内存,并逐行处理:
python将文件本身作为一个行序列,历遍文件的所有行可以直接这样完成:
fname = input("请输入要打开的文件:")
fo = open(fname, "r")
for line in fo:
print(line) # 处理一行数据
fo.close
拓展:文件的换行符
如果采用二进制方式打开文件,换行符只是一个符号,对应一个字节,表示为“\n”;如果采用文本方式打开文件,换行符表示一行的结束,辅助程序对文件的处理。文件的换行符是真实存在的一个字符。
Python提供3个与文件内容写入有关的方法,如下所示(文件打开模式含有w、a、x、+):
方法 | 含义 |
---|---|
.write(s) | 向文件写入一个字符串或字节流 |
.writelines(lines) | 将一个元素全为字符串的列表写入文件 |
.seek(offset) | 改变当前文件操作指针的位置,offset的值:0—文件开头;1—当前位置;2—文件结尾 |
>>> f = open("1.txt","a+")
>>> f.write("hello")
5
# 代码到此,文件1.txt还没“hello”因为它还在缓存区
>>>f.close() # 此时文件1.txt在后面加上“hello”
>>> f = open("1.txt","a+")
>>> f.write("2a") # 在文件1.txt后面加上2a
2
>>> a = ['1','1','2']
>>> f.writelines(a)
>>> f.close() # 文件1.txt在文本后面加上了112
P.S. 注意写入后的元素间是没有分隔符的
例:向文件写入一个列表
向文件写一个列表类型,并打印输出结果,代码如下:
fname = input("请输入要写入的文件")
fo = open(fname,"w+")
ls = ['唐诗','宋词','元曲']
fo.writelines(ls)
for line in fo:
print(line)
fo.close()
程序执行结果如下:
>>>请输入要写入的文件test.txt
>>>
在WriteListFile.py程序的目录中找到text.txt文件,打开可以看到其中的内容如下:
唐诗宋词元曲
列表ls内容被写入文件,但为何
for line in fo:
print(line)
fo.close()
没有将这些内容打印出来呢?
因为文件写入内容后,当前文件操作指正在写入内容的后面,此处的代码从指针开始向后读入并打印内容,被写入的内容却在指针前面,因此未能被打印出来。
所以为了可以在写入文件后增加一条代码fo.seek(0)将文件操作指针返回到文件开始,即可显示写入的内容,代码如下:
fname = input("请输入要写入的文件:")
fo = open(fname, "+w")
ls = ["唐诗", "宋词", "元曲"]
fo.writelines(ls)
fo.seek(0)
for line in fo:
print(line)
fo.close()
程序执行结果如下
请输入要写入的文件:test.txt
唐诗宋词元曲
fo.writelines()方法并不在列表后面增加换行,只是将列表内容直接排列输出。
<file>.seek(offset[,where])
seek方法可以移动指针的位置
where定义指针位置的参照点:
offset参数:定义了指针相对于参照点where的具体位置,取整数值。
例:文件起始位置
f.seek(0)
例:文件其实位置,往文件为方向移动3个字节
f.seek(3)或f.seek(3,0) # 3 往文件方向移动3个字节, 0为文件开头
例:从当前位置开始,往文件头方向移动2个字节
f.seek(-2,1) # -2 往文件头方向移动2个字节,1 当前位置
f.tell(): 返回文件操作标记的当前位置,以文件的开头为原点
>>> f = open("1.txt","ab+")
>>> f.tell()
42
上下文管理语句with
在实际开发中,读写文件应优先考虑使用上下文管理语句with,关键字with可以自动管理资源,不论因为什么原因(哪怕是代码引发了异常)跳出了with块,总能保证文件被正确关闭。简而言之,就是使用with语句可以不用加close()
with open(filename,mode,encoding)as fp: #这里写ton过文件对象fp读写文件内容的语句
上下文管理语句with还支持下面的用法:
with open('1.txt','r')as src, open('1_new.txt','w') as dst:
dst.write(src.read())
例:向文本文件中写入内容,然后读出:
>>> s = "Hello world\n文本文件的读取方法\n文本文件的写入方法\n"
>>> with open('1.txt','w')as fp:
fp.write(s)
>>> with open('1.txt')as fp:
print(fp.read())
Hello world
文本文件的读取方法
文本文件的写入方法
课堂:
思考7_1:下面的代码
f = open("text.txt",'wb+') # 打开text.txt文件以覆盖写模式,二进制文件模式以及在此基础上同时增加读写功能
f.write(b"python") # 二进制的python写入
f.seek(2,0) # 光标为文件方向的第2个字节,光标在文件开头
print(f.read(3)) # 读取光标位置向后数3个字节 光标移动到第5个字节
f.seek(-3,1) # 光标移到方向头为开头3个字节,光标在当前位置 从第5个字节移到第2个字节
print(f.read(1)) # 读取文件光标位置向后数1个字节
f.close()
结果为:
b'tho'
b't'
思考7_2:复制1.txt文件,生成一个名为1_1.txt新的文本文件
答:
f1 = open("1.txt","r",encoding='utf-8')
f2 = open("1_1.txt","w")
a = f1.read()
f2.write(a)
f1.close()
f2.close()
或:
f1 = open("1.txt","r",encoding='utf-8')
f2 = open("1_1.txt","w")
for i in f1:
f2.write(i)
f1.close()
f2.close()
思考7_3:生成1至122之间的随机整数数,转成对应的字符,然后将满足以下条件(大写字母、小写字母、数字和一些特殊符号’*‘,’&‘,’^‘,’$‘)的字符逐一输入写入文本test.txt中,当光标位置达到101时停止写入。
判断是否小写字母的方法:字符串.islower()
判断是否大写字母的方法:字符串.isupper()
判断是否数字的方法:字符串.isdigit()
答:
产生随机整数 randint()
转成对应的字符 chr()
chr() in [’*‘,’&‘,’^‘,’$‘]
达到101个字节 f.tell()
import random
f1=open("test.txt",'w+')
while f1.tell() <= 101:
a=chr(random.randint(1,122))
if a.islower() or a.isupper() or a.isdigit() or a in['*','&','^','$']:
f1.write(a)
f1.close()
输出结果:
打开text.txt文件
ln7KSuL5qRzQ7LJRmH5O6FOiyrKHCL$^mHwlYoVJo*DmP8MPKQKpH4uun*L*ZE91lEEs&tdtEKTSrMqxI9BwHb63fefiapy9J^VY1t
思考7_4:
逐个字节读取:'fy.txt’文件,输出该文件前10个字节字符和后10个字节字符
fy = open("fy.txt",'rb') # 注意要使用rb方式打开,下面才可进行读写 不然会报错.UnsupportedOperation: can't do nonzero end-relative seeks
fy.seek(0)
print(fy.read(10))
fy.seek(-10,2)
print(fy.read(10))
fy.close()
程序结果:
b'1.The Chin'
b'nto orbit.'
思考7_5:
统计‘fy.txt’文件中大写字母、小写字母和数字的个数。可以利用字符串的isupper()、islower()和isdigit()方法。
输入如下所示:
大写有6个,小写有205个,数字有4个
答:
f=open("fy.txt","r")
a=f.read()
s=0
y=0
c=0
for i in a:
if i.isupper():
s=s+1
elif i.islower():
y=y+1
elif i.isdigit():
c=c+1
else:
pass
f.close()
print("大写有"+str(s)+"个, "+"小写有"+str(y)+"个, 数字有"+str(c)+"个")
程序结果:
大写有6个, 小写有205个, 数字有4个
代码简化
f = open("fy.txt").read() # 字符串
s,y,c=0,0,0
while 1:
if f.isupper():
s+=1
elif f.islower():
i+=1
elif f.isdigit():
d+=1
if not f:
break
f.close()
print('大写有{}个,小写有{}个,数字有{}个',format(s,y,c))
思考与练习
7.1 读写文件需要采用open()函数,采用绝对路径打开操作系统中的一个文件。
答:
向文件中读写数据的方法:
read()
readline()
readlines()
write()
writelines()
seek()
tell()
要点:PIL库是一个具有强大图像处理能力的第三方库,不仅包含了丰富的像素、色彩操作功能,还可以用于图像归档和批量处理。
PIL(Python Image Library)库是Python语言的第三方库,需要通过pip工具安装。安装PIL库的方法如下:
:\> pip3 install pillow
PIL库支持图像存储、显示和处理,它能够处理几乎所有图片格式,可以完成对图像的缩放、裁剪、叠加以及向图像添加线条
要点:数据组织存在维度,列表类型用于表示和处理一维和二维数据
根据数据的关系不同,数据组织可以分为一维数据、二维数据和高维数据。
一维数据:由对等关系的有序或无序数据构成,采用线性方式组织,对应于数学中的数组和集合等概念。
例如,国籍经济合作论坛20国集团(G20)的成员是对等关系,表示为一维数据,内容如下。无论采用任何方式分隔和表示,一维数据都具有线性特点。
中国、美国、日本、德国、法国、英国、意大利、加拿大、俄罗斯、欧盟
二维数据:也称表格数据,由关联关系数据构成,采用表格方式组织,对应于数学中的矩阵,常见的表格都属于二维数据。
例如,国家统计局发布的大中小城市新建住宅价格指数是二维数据,其中表格说明部分(第一行)可以看作是二维数据的一个维度,也可以看作是数据外的说明。
城市 | 环比 | 同比 | 定基 |
---|---|---|---|
北京 | 101.5 | 120.7 | 121.4 |
上海 | 101.2 | 127.3 | 127.8 |
环比:上月=100;同比:上年同月=100;定基:2015年=100
高维数据:由键值对类型的数据构成,采用对象方式组织,属于整合度更好地数据组织方式。高维数据在网络系统中十分常用,HTML、XML、JSON等都是高维数据组织的语法结构。
例如:
"writer":[
{"first name":"A",
"second name":"B",
"job":"C"},
{"first name":"a",
"second name":"b",
"job":"c"}
]
数据包括文件存储和程序使用两个状态。存储不同维度的数据需要适合维度特点的文件存储格, 处理不同维度数据的程序需要使用想适应的数据类型或结构。
对于数据处理,需要考虑存储格式以及表示和读写等两个问题。
一维数据是最简单的数据组织类型,有多种存储格式,常用特殊字符分隔,分隔方式如下:、
用一个或多个空格分隔,例如:
中国 美国 日本 德国 法国 英国
用逗号分隔,注意,逗号为英文输入法中的半角逗号,例如:
中国,美国,日本,德国,法国,英国
用其他符合或符号组合分隔,建议采用不出现在数据中的特殊符号,例如:
中国;美国;日本;德国;法国;英国;
二维数据由多条一维数据构成,可以看成是一维数据的组合形式。
一种国籍通用的一二位数据存储格式:CSV格式。来源于使用逗号分隔的一维数据表示方式。
逗号分割数值的存储格式叫做CSV格式(Comma-Separated Values),常应用在程序之间转移表格数据。该格式的应用有如下一些基本规则。
(1)纯文本模式,通过单一编码表示字符
使用某个字符集,比如ASCII、Unicode、EBCDIC或GB2312
(2)以行为单位,开头不留空行,行之间没有空行
(3)每行表示一个一维数据,多行表示二维数据
(4)以逗号(英文、半角)分隔每列数据,列数据为空也要保留逗号。
(5)对于表格数据,可以包含或不包含列名,包含时列名放置在文件第一行。
城市,环比,同比,定基
北京,101.5,120.7,121.4
上海,101.2,127.3,127.8
CSV格式存储的文件一般采用.csv为拓展名。
拓展:Python的csv标准库
Python提供了一个读写csv的标准库,可以通过import csv使用。csv库包含操作CSV格式最基本的功能,csv.reader()和csv.writer()。由于CSV格式十分简单,对于一般程序来说,建议程序员自己编写操作CSV格式的函数,这样更灵活和个性化。对于需要运行在复杂环境或商业使用的程序,建议采用csv标准库。
CSV文件的每一行是一维数据,可以使用Python中的列表类型表示,整个CSV文件是一个二维数据,由表示每一行的列表类型作为元素,组成一个二维列表。
例:导入CSV格式数据到列表
fo = open("chenshi.csv",'r')
ls = []
for line in fo:
line = line.replace("\n","") #每行最后一个元素都包含了\n,多余了用replace方法去掉
ls.append(line.split(",")) #split()通过指定的分隔符对字符串进行切片。如果参数 num 有指定值,则分隔 num+1 个子字符串
print(ls)
fo.close()
程序结果:
[['城市', '环比', '同比', '定基'], ['北京', '101.5', '120.7', '121.4'], ['上海', '101.2', '127.3', '127.8']]
上例从CSV文件中一次性读入全部数据写入列表,之后,在程序内部使用列表即可表达数据,这种一次性读入方式适合一部分应用。另一部分应用并不需要将数据全部读入程序再操作,可以逐行督促CSV文件,逐行运算处理,这种情况仅使用普通列表即可。
例:逐行处理CSV格式数据
从CSV文件中读取数据,去掉内容中的逗号,打印到屏幕,代码如下:
fo = open("chenshi.csv",'r')
ls = []
for line in fo:
line = line.replace("\n","")
ls = line.split(",") # 每一行根据”,“ 进行分割
lns = ""
for s in ls:
lns += "{}\t".format(s) # \t代表制表符
print(lns)
fo.close()
或:
fo = open("chenshi.csv",'r')
ls = []
for line in fo:
line = line[:len(line)-1] # 每一行长度-1即把回车符\n删掉
ls = line.split(",")
for s in ls:
print(s,end="\t") # 原本print是另起一行,end=说明打印后跟空格,即不换行直接在后面输出
print()
fo.close()
程序结果:
城市 环比 同比 定基
北京 101.5 120.7 121.4
上海 101.2 127.3 127.8
对于Python列表变量保存的一维数据结果,可以用字符串的join()方法组成逗号分隔形式再通过文件的write()方法存储到CSV文件中。其中”,“.join(ls)生成一个新的字符串,它由字符串”,“分隔列表ls中的元素形成。
[例] 一维数据写入CSV文件
将一维数据[‘北京’,‘101.5’,‘120.7’,‘121.4’]写入chenshi2.csv文件代码如下:
chenshi2.csv:
城市,环比,同比,定基
上海,101.2,127.3,127.8
fo = open("chenshi2.csv",'w')
ls = ['北京','101.5','120.7','121.4']
fo.write(",".join(ls)+"\n")
fo.close()
结果chenshi2.csv则变为:
北京,101.5,120.7,121.4
对于列表中存储的二维数据,可以通过循环写入一维数据的方式写入CSV文件,参考代码样式如下:
for row in ls:
<输出文件>.write(",".join(row)+"\n")
[例]二维数据写入CSV文件
读入chenshi.csv文件,将其中的数据独出,将数字部分计算百分比后输出到chenshiut.csv文件。输出的CSV文件内容如下:
整个程序分为3个部分:首先将原始文件中的数据全部导入,用列表方式表示;第二,对列表中的元素逐行判断,对浮点数值进行百分比运算,运算结果写回列表;第三,将更新后的列表输出新的CSV文件,代码如下:
fr = open("chenshi.csv","r")
fw = open("chenshioout.csv","w")
ls = []
for line in fr: # 将CSV文件中的二维数据读入到列表变量
line = line.replace("\n","")
ls.append(line.split(","))
print(ls)
for i in range(len(ls)): # 遍历列表变量计算百分数
for j in range(len(ls[i])):
if ls[i][j].replace(".","").isnumeric(): # 用于判断一个字符串是否类似"101.5"由数字或小数点构成。由于python中没有单个函数能够直接判断,因此通过replace()方法将其中可能的小数点去掉,再通过isnumeric()方法判断其余字符是否都是数字。这是一种不完备的判断方式。但在该例的应用背景下可以使用。
ls[i][j] = "{:.2}%".format(float(ls[i][j])/100) #
for row in ls: # 将列表变量中的量为数据输出到CSV文件
print(row)
fw.write(",".join(row)+"\n")
fr.close()
fw.close()
思考7_6:现在要向chenshi.csv文件追加记录:
[‘广州’,‘101.3’,‘119.4’,‘120.0’],
答:代码如下:
fo = open("chenshi.csv","a+") # 追加模式
ls='广州,101.3,119.4,120.0\n' # 此处 ls应为str形式,而不是列表形式
fo.write(ls)
fo.close()
结果chenshi.csv则变为:
城市,环比,同比,定基
北京,101.5,120.7,121.4
上海,101.2,127.3,127.8
北京,101.5,120.7,121.4
广州,101.3,119.4,120.0
思考7_7:现在要向chenshi.csv文件追加记录:
ls=[‘深圳’,‘102.0’,‘140.9’,‘145.5’]
fo = open("chenshi.csv","a+")
ls = '深圳,102.0,140.9,145.5\n'
fo.write(ls)
fo.close()
结果chenshi.csv则变为:
城市,环比,同比,定基
北京,101.5,120.7,121.4
上海,101.2,127.3,127.8
北京,101.5,120.7,121.4
广州,101.3,119.4,120.0
深圳,102.0,140.9,145.i
思考7_8
1.创建csv文件,命名为sec.csv
2.用Python编程将下面三行数据写入sec.csv
新基建 铸就高质量发展的“硬核”支撑
新模式 充分释放中国超大市场潜力
新经济 为发展插上“数字经济”的翅膀
3.读取文件内容
fo = open("sec.csv","a+")
ls1 = "新基建 铸就高质量发展'硬核'支撑\n"
ls2 = "新模式 充分释放中国超大市场潜力\n"
ls3 = "新经济 为发展插上'数字经济'的翅膀\n"
fo.write(ls1)
fo.write(ls2)
fo.write(ls3)
fo.close()
fo = open("sec.csv","r")
a = fo.read()
print(a)
结果为:
新基建 铸就高质量发展'硬核'支撑
新模式 充分释放中国超大市场潜力
新经济 为发展插上'数字经济'的翅膀
思考与练习:
7.12 请描述数据维度的含义
答:数据维度是数据”立体“结构中中独立坐标的数目,是用数据描述事物或现象的特征数目,比如性别、地区、时间等都是维度。一维数据一般是线性结构,二维数据一般是表格数据,高维数据采用对象方式组织。
7.13 JSON是一种什么样的数据格式?
答:JSON是一种轻量级的数据交换格式,其实就是讲一组数据转化为字符串,它包含两种数据类型:对象和数组
7.14 思考CSV格式能否支持高维数据表示
答:可以支持,对CSV来说,高维相当于对数据分页,只要把几页数据放到一个CSV里,并在程序中约定好维度,就相当于实现了CSV的高维数据存储。
要点:json库是处理JSON格式的Python标准库
JSON格式:
JSON(JavaScript Object NOtation): 一种与开发语言无关的、轻量级的数据库存储格式
它是一种数据格式的标准规范,起初来源于JavaScript这门语言,后来随着使用的广泛,几乎每门开发语言都有处理JSON的API
优点:易于人的阅读和编写,易于程序解析与生产。
1.JSON的Object数据类型 ,如下所示:
{key:value, key:value…}
Key:string类型
value:任何基本类型或数据结构
2.JSON的Array数据类型
[value,value…]
Value:任何基本类型或数据结构
比如:{“name”:“李广”,“values”:[1,2,45,“你好”]}
JSON数据类型 | Python数据类型 |
---|---|
object | dict |
array | list |
string | str |
number(int) | int |
number(real) | float |
true | True |
false | False |
null | None |
导入方式如下:
import json
json库主要包括两类函数:操作类函数和解析类函数
操作类函数:主要完成外部JSON格式和程序内部数据类型之间的转换功能
解析类函数:主要用于解析键值对内容。
json格式包括对象和数组,用大括号{}和方括号[]表示,分别对应键值对的组合关系和对等关系。一般来说JSON格式的对象将被json库解析为字典,JSON格式的对象将被json库解析为字典,JSON格式的数组将被解析为列表。
json库是处理JSON格式的Python标准库
它包含了两个函数:
dumps()
:对数据进行编码loads()
:对数据进行解码json库包含两个过程:编码(encoding)和解码(decoding)。编码是将Python数据类型变换成JSON格式的过程,解码是从JSON格式找那个解析数据对应到PYthon数据类型的过程。本质上,编码和解码是数据类型序列化和反序列化的过程。
拓展:序列化
序列化是指将对象数据类型转换为可以存储或网络传输格式的过程,传输格式一般为JSON或XML。反序列化指从存储区域中将JSON或XML格式读出并重建对象的过程。JSON序列化与反序列化的过程分别是编码和解码。
下表列出了json库的4个操作类函数,其中dumps()和loads()分别对应编码和解码功能。
函数 | 描述 |
---|---|
json.dumps(obj, sort_keys=False, indent=None ) | 将Python的数据类型转换为JSON格式,编码过程 |
json.loads(string) | 将JSON格式字符串转换为Python的数据类型,解码过程 |
json.dump(obj,fp,sort_keys=False, indent=None) | 与dumps()功能一致,输出到文件fp |
json.load(fp) | 与loads()功能一致,从文件fp读入 |
json.dumps()中的obj可以是Python的列表或字典类型,当输入字典类型时,dumps()函数将其变为JSON格式字符串。默认生成的字符串是顺序存放的,sort_keys可以对字典元素按照key进行排列,控制输出结果。indent参数用于增加数据缩进,使得生成的JSON格式字符串更具有可读性。
>>> import json
>>> dt = {'b':2,'c':4,'a':6}
>>> s1 = json.dumps(dt) # dumps 返回JSON格式的字符串类型
>>> s2 = json.dumps(dt,sort_keys=True,indent=4)
>>> print(s1)
{"b": 2, "c": 4, "a": 6}
>>> print(s2)
{
"a": 6,
"b": 2,
"c": 4
}
>>> print(s1==s2)
False
>>> dt2 = json.loads(s2)
>>> print(dt, type(dt2))
{'b': 2, 'c': 4, 'a': 6} <class 'dict'>
尽管json库还要很多丰富的功能,但是json库一般用于JSON格式和其他类型格式转换,所以,掌握基本用法即可。
import json
dt = {'b':2,'c':4,'a':6}
s1 = json.dumps(dt) # dumps返回JSON格式的字符串类型
print(s1,type(dt))
dt2 = json.loads(s1)
print(dt2,type(dt2))
with open('test.json','w')as f: # 打开test.json文件
json.dump(dt,f) # 按照json编码写入的
with open('test.json','r')as f:
data = json.load(f)
程序结果:
{"b": 2, "c": 4, "a": 6} <class 'dict'>
{'b': 2, 'c': 4, 'a': 6} <class 'dict'>
对word文档的操作:
python-docx是一个操作word文档非常好用的python库
需先用pip install python-docs
安装第三方库
import docx
思考与练习
7.21 json库的dumps()函数的sort_keys参数有何作用?
答:sorted_key 用来决定是否对字典中字典项按键进行排序
7.22 判断题:json库的dumps()函数将Python字典类型变成字符串。
答:√
7.23 判断题:json库的dumps()函数将Python列表类型变成字符串。
答:√
1.创建一个6_1.txt文件,提醒用户输入一些信息,当用户输入-1时结束输入;把用户的输入都保存到6_1.txt文件中,然后把该文件全部显示出来。
解:
f = open("6_1.txt", "a+")
x=input("请输入要编写的内容(输入-1结束输入):")
while x != '-1':
f.write(x+'\n')
x=input("请输入要编写的内容(输入-1结束输入):")
f.seek(0,0)
print(f.read())
f.close()
程序结果:
请输入要编写的内容(输入-1结束输入):23423
请输入要编写的内容(输入-1结束输入):435245
请输入要编写的内容(输入-1结束输入):134234
请输入要编写的内容(输入-1结束输入):Iloveyou
请输入要编写的内容(输入-1结束输入):-1
fefe adfe
23423
435245
134234
Iloveyou
2.在text.csv文件记录了某个班级所有学生的名字、学号和3科成绩,要求读取该文件,计算每个学生的总成绩并输出,统计出每科的平均成绩并输出。请编程实现,程序保存为学号_2.py
输出如下所示:
1001 Make 221
1002 Linda 246
1003 Jone 247
数学平均:84.67;英语平均:69.67;语文平均:83.67
解:
f=open("text.csv",encoding='gbk')
stu=[]
j=0
f.readline()
for i in f.readlines():
i=i[:len(i)-1]
stu.append(i.split(","))
stu[j][2]=int(stu[j][2])
stu[j][3]=int(stu[j][3])
stu[j][4]=int(stu[j][4])
s=sum(stu[j][2:5])
print(stu[j][0],'\t',stu[j][1],'\t',s)
j=j+1
s1=0;s2=0;s3=0
for i in range(0,j):
s1=stu[i][2]+s1
s2=stu[i][3]+s2
s3=stu[i][4]+s3
程序j结果:
1001 Make 221
1002 Linda 246
1003 Jone 247
数学平均:84.67;英语平均:69.67;语文平均:83.67