操作系统的文件分为:
(1)文本文件:.txt
(2)二进制文件:.mp3、.wma、.doc
一、获取文件对象
运用open函数来获得 文件对象
格式为:open(file,mode)
file: 泛指文件和文件夹,
相对路径:从当前路径开始的路径
绝对路径:从盘符开始的路径如:“E:\test”
mode模式说明:
r:(1)读模式(默认模式),用来读取文件内容。文件指针在文件的开头。文件需要事先存在,否则会产生异常。
w:(1)写模式,用来向文件写入数据。文件指针在文件的开头。如果文件存在,则覆盖文件,否则会创建文件。
a:(1) 追加模式,用来向文件追加数据。文件指针在文件的末尾。如果文件存在,不会覆盖文件(追加写入),否则会创建文件。
x:(1) 写模式,用来向文件写入数据。文件指针在文件的开头。如果文件不存在,创建文件,否则产生错误。
t:(2) 文本(字符串)模式(默认模式),以文本形式操作文件。
b:(2) 二进制(字节)模式,以二进制形式操作文件。
U:(3) 通用换行符模式(已不建议使用)。在该模式下,\n,\r\n或\r都会解析为换行符。不能与w、a、x或+模式同时使用(仅限于读取文件时使用)。
+:(3) 读取或写入。
(1)(2)(3)模式中,不同组的模式可同时使用、(1)默认值是r、(2)默认值是t
f = open(r"E:\test\test1.txt","rt")
print(f)
二、关闭文件
关闭文件的几种方法:
(1)直接关闭
(2)try finally中
(3)with打开和关闭 (推荐)
使用with打开文件 with open(…) as 文件对象名1, open(…) as 文件名2
with open(r"E:\test\test1.txt","r") as f1, open(r"E:\test\test2.txt") as f2:
print(f1.read())
print(f2.read())
输出:
hello python2hello python2
hello python2hello python2
三、文件的读取
(1) read(size): size不写或者-1代表将文件内容全部读出,size>0整数 读取对应的字节
with open(r"E:\test\test1.txt","r") as f:
print(f.read())
输出:
hello python
浣犲ソpython
如果要正确的显示出中文字符,需要加上encoding="utf-8"
参数
如下所示:
with open(r"E:\test\test1.txt","r",encoding="utf-8") as f:
print(f.read())
输出:
hello python
你好python
文件对象是迭代器,当读取到文件的末尾,无法再读取任何内容,返回空
如下文本信息为abc
with open(r"E:\test\test1.txt","r",encoding="utf-8") as f:
print(f.read(1))
print(f.read(1))
print(f.read(1))
print(f.read(1))
输出:
a
b
c
**(2)readline()**返回文件的一行,保留原文档中\n,将\n也认为是读取的内容
如下文本信息为:
hello1
hello2
hello3
代码执行情况如下:
with open(r"E:\test\test1.txt","r",encoding="utf-8") as f:
print(f.readline())
print(f.readline())
print(f.readline())
print(f.readline())
输出:
hello1
hello2
hello3
(3)readlines() 返回一个列表,每一个元素都是文件中的一行
with open(r"E:\test\test1.txt","r",encoding="utf-8") as f:
print(f.readlines())
输出:
['hello1\n', 'hello2\n', 'hello3\n']
(4)通常如果文件过大,我们使用for循环的方式对文件对象进行迭代,文件会按行输出
文本信息为:
hello1 hello2
hello2
hello3
代码执行情况为:
with open(r"E:\test\test1.txt","r",encoding="utf-8") as f:
for i in f:
print(i,end="")
输出:
hello1 hello2
hello2
hello3
四、文件的写入
(1)write(content)方法
with open(r"E:\test\test1.txt","w+",encoding="utf-8") as f:
f.write("hello2")
(2)writelines(lines) :将lines列表中的内容写入文件
with open(r"E:\test\test1.txt","w+",encoding="utf-8") as f:
f.writelines(["hello1\n","hello2\n"])
五、文件的定位
文件的指针:
当r或者w模式的时候,指针的位置是在文件的开头0(空文件也在0的位置)
当a模式的,指针的位置在文件末尾最后一个字符的下一个位置。
with open(r"E:\test\test1.txt","r",encoding="utf-8") as f:
print(f.tell())
with open(r"E:\test\test2.txt","w",encoding="utf-8") as f:
print(f.tell())
with open(r"E:\test\test3.txt","a",encoding="utf-8") as f:
print(f.tell())
输出:
0
0
6
(1)tell: 返回指针的位置,即下一个要读取或者要写入字节的位置
with open(r"E:\test\test1.txt","r",encoding="utf-8") as f:
print(f.tell())
f.read(1)
print(f.tell())
输出:
with open(r"E:\test\test1.txt","r",encoding="utf-8") as f:
print(f.tell())
f.read(1)
print(f.tell())
**(2)seek(offset,whence)😗*改变指针位置
offset:指定偏移量
whence:指定偏移量参照位置:
0 SEEK_SET-----从文件头开始计算
1 SEEK_CUR-----从文件当前的位置
2 SEEK_END-----从文件尾开始计算
对于whence=0的时候,可以指定b模式或者t模式
对于whence=1或2时候,只支持b模式,当t模式的是,偏移量只能是0才是有效的
如下代码文本信息为012345
with open(r"E:\test\test1.txt","br") as f:
print(f.read(1))
print(f.tell())
f.seek(3,0)
print(f.tell())
print(f.read(1))
f.seek(0,0)
print(f.tell())
print(f.read(1))
f.seek(1,1)
print(f.read(1))
f.seek(-1,2)
print(f.read())
输出:
b'0'
1
3
b'3'
0
b'0'
b'2'
b'5'
t模式下对于whence=1或2时候,只支持b模式,当t模式的是,偏移量只能是0才是有效的
with open(r"E:\test\test1.txt","tr") as f:
print(f.read(1))
print(f.tell())
f.seek(3,0)
print(f.tell())
print(f.read(1))
f.seek(0,0)
print(f.tell())
print(f.read(1))
f.seek(0,1)
print(f.read(1))
f.seek(0,2)
print(f.read())
print(f.tell())
输出:
0
1
3
3
0
0
1
6
六、文件与路径的操作
1 .os模块
(1) mkdir: 父目录必须存在,被创建的目录必须不存在,否则报错
import os
os.mkdir(r"E:\test\mkdir_test")
import os
os.mkdir(r"E:\test1\mkdir_test")
输出:
FileNotFoundError: [WinError 3] 系统找不到指定的路径。: 'E:\\test1\\mkdir_test'
(2)makedirs: 父目录可以不存在,会同时创建父目录
import os
os.makedirs(r"E:\test1\mkdir_test")
(3)rmdir:删除空目录
os.rmdir(r"E:\test1\mkdir_test")
(4)删除空目录,删完还会查看父目录是否也为空,如果也为空,则删除父目录,直到文件夹不为空为止
import os
os.makedirs(r"E:\test1\mkdir_test")
os.removedirs(r"E:\test1\mkdir_test")
(5)删除文件,如果文件不存在,也不会报错
import os
os.remove(r"E:\test\test1.txt")
(6)rename 重命名文件或者目录
import os
os.rename(r"E:\test\test2.txt",r"E:\test\test22.txt")
(7)renames (剪切粘贴)重命名文件,可以应用不同的路径下(不能运用在不同磁盘中):
相当于把原来路径下的内容删掉,在新路径下新创建一个文件
import os
os.renames(r"E:\test\test22.txt",r"E:\test1\test22.txt")
os.remove(r"E:\test1\test22.txt")
os.rmdir(r"E:\test1")
**(8) getcwd()**返回当前工作目录
import os
cur_path = os.getcwd()
print(cur_path)
(9) walk 遍历路径下的文件
会显示每一层文件的情况
(1)dirpath: string 代表目录的路径,起始路径
(2)dirnames :list 包含dirpath下的所有子目录名字
(3)filenames:list 包含非目录文件的文件名
实际储存结构如下:
t = os.walk(r"E:\test")
for roots,dirs,files in t:
print(roots,end="\t[roots]\n")
print(dirs,end="\t[dirs]\n")
print(files,end="\t[files]\n")
输出:
E:\test [roots]
['test1'] [dirs]
['test3.txt'] [files]
E:\test\test1 [roots]
[] [dirs]
['test1_next.txt'] [files]
(10)显示参数路径下的第一层目录名字,包括文件个路径(文件夹)
import os
t = os.listdir(r"E:\test")
print(t)
输出:
['test1', 'test3.txt']
2.os.path
**(1)abspath(path):**返回当前文件所在绝对路径
print(os.path.abspath("."))
(2)basepath返回路径中最后面部分,以/分隔符为准(只是字符串的处理,忽略路径是否真实存在)
import os.path
print(os.path.basename(r"E:\test\test1"))
输出:
test1
**(3)commonpath:**返回列表中所有路径的最长公共路径
import os.path
print(os.path.commonpath([r"E:\test\test1",r"E:\test\test2"]))
输出:
E:\test
(4)exist 判断路径是否存在
import os.path
print(os.path.exists(r"E:\test\test1"))
输出:
True
(5)返回目录或者文件的最后访问时间,修改时间
import os.path
print(os.path.getatime(r"E:\test\test3.txt"))
print(os.path.getctime(r"E:\test\test3.txt"))
输出:
1596352967.0744138
1596352552.2928417
(6)getsize获得文件的大小 字节为单位
import os.path
print(os.path.getsize(r"E:\test\test3.txt"))
输出:
6
(7)判断是否存在目录或者文件
import os.path
print(os.path.isdir(r"E:\test\test3.txt"))
输出:
False
(8)join路径的拼接
绝对路径前的元素都去掉
空元素会去掉
print(os.path.join("abc", "c:/", "def", "", "ghi"))
输出:
c:/def\ghi
(9)拆路径: dirname和basename
import os.path
print(os.path.split("c:/abc/def/ghi.jpg"))
输出:
('c:/abc/def', 'ghi.jpg')
3. shutil模块
(1)复制:复制内容
如果目标文件夹不存在,不会报错也不会执行
import shutil
shutil.copy(r"E:\test\test3.txt",r"E:\test\test1")
(2)copy2 把元信息都复制,包含文件的创建时间等等信息
import shutil
shutil.copy2(r"E:\test\test3.txt",r"E:\test\test1")
(3)copytree 复制目录,连同子目录和文件都复制
目标文件不能存在,否则报错:
FileExistsError: [WinError 183] 当文件已存在时,无法创建该文件。: 'E:\\test\\test2'
shutil.copytree(r"E:\test",r"E:\test\test2")
七、序列化
即把list转换成str,有如下优点:1、传输快;2、解析list的任务给了客户端
序列化的形式有如下三种:
1、csv;
2、json;
3、pickle;
1、csv
向csv格式的文件中写数据,一次写一行:writerow
import csv
with open("c:/abc/test.csv","wt") as f:
writer=csv.writer(f)
writer.writerow(["姓名","年龄","小组"])
writer.writerow(["张三","15","A组"])
writer.writerow(["李四","16","B组"])
向csv格式的文件中写数据,一次写多行:writerows
newline表示写操作的时候,调用一次witer会加\n
import csv
with open(r"D:\test/test.csv","wt") as f:
writer=csv.writer(f)
writer.writerows([["姓名","年龄","小组"],["张三","15","A组"],["李四","16","B组"]])
2、json:javascript object notation
轻量级的数据交换格式
采用键值映射,:
对象:{}
数组:[]
字符串:""
布尔类型:true false
数值:5 2.8
python的数据类型跟json几乎一致,python和json的之间转换很方便
1、从python的字典数据转换成json的文件:【dump】
第一个参数是要写入的数据,第二个参数是文件对象
ensure_ascii=默认值是True,如果希望显示中文ensure_ascii=False
d={
"bg": "green",
"title": {
"data": ["data1", "data2", "data3", "data4"],
"align": "左对齐"
}
}
import json
with open("d:/test/test.json","wt") as f :
json.dump(d,f,ensure_ascii=False)
2、将json格式的转换成python类型数据
d={
"bg": "green",
"title": {
"data": ["data1", "data2", "data3", "data4"],
"align": "左对齐"
}
}
import json
with open("d:/test/test.json","wt") as f :
json.dump(d,f,ensure_ascii=False)
with open("d:/test/test.json","rt") as f :
d=json.load(f)
print(type(d))
print(d)
输出:
<class 'dict'>
{'bg': 'green', 'title': {'data': ['data1', 'data2', 'data3', 'data4'], 'align': '左对齐'}}
3序列化和反序列化
序列化:将字典类型的对象转换成字符串 dumps
第一个参数:需要序列化的字典对象,ensure_ascii=False
d={
"bg": "green",
"title": {
"data": ["data1", "data2", "data3", "data4"],
"align": "左对齐"
}
}
import json
s=json.dumps(d,ensure_ascii=False)
print(type(s))
print(s)
输出:
<class 'str'>
{"bg": "green", "title": {"data": ["data1", "data2", "data3", "data4"], "align": "左对齐"}}
反序列化:将字符串转换成python中字典 loads;
第一个参数:需要反序列化的字符串对象
d={
"bg": "green",
"title": {
"data": ["data1", "data2", "data3", "data4"],
"align": "左对齐"
}
}
import json
s=json.dumps(d,ensure_ascii=False)
d2=json.loads(s)
print(type(d2))
print(d2)
输出:
<class 'dict'>
{'bg': 'green', 'title': {'data': ['data1', 'data2', 'data3', 'data4'], 'align': '左对齐'}}
4、python中的字典和json类型之间映射
import json
d_new={
"布尔类型":False,
"空值类型":None,
"浮点类型":1.5,
"整数类型":1,
"字符串":"abc",
"列表/数组":[1,2,3],
"字典/对象":{"one":1,"two":2}
}
print(json.dumps(d_new,ensure_ascii=False))
输出:
{"布尔类型": false, "空值类型": null, "浮点类型": 1.5, "整数类型": 1, "字符串": "abc", "列表/数组": [1, 2, 3], "字典/对象": {"one": 1, "two": 2}}
5、自定义序列化类型,继承JSONEncoder,重写default方法
import json
class Person:
def __init__(self,name,age):
self.name=name
self.age=age
p=Person("张三",20)
class PersonEncoder(json.JSONEncoder):
def default(self, o):
# 变成字典
if isinstance(o,Person):
return {"name":o.name,"age":o.age,"自定内容":"自定义的值"}
else:
return super().default(o)
# 调用自定义的序列化
json_str=json.dumps(p,cls=PersonEncoder,ensure_ascii=False)
print(json_str)
print(type(json_str))
3、pickle
第一个参数是需要序列化的对象
第二个参数是序列化之后存储的文件
import pickle
class Person:
def __init__(self,name,age):
self.name=name
self.age=age
p=Person("张三",20)
with open("d:/test/person.pickle","wb") as f:
pickle.dump(p,f)
with open("d:/test/person.pickle","rb") as f:
p2=pickle.load(f)
print(type(p2))
print(p2.name)
print(p2.age)
输出:
<class '__main__.Person'>
张三
20
八、上下文管理器
with语句体实现的是上下文管理器,在with开始执行和退出的时候,会自动调用一些魔法方法。
开始执行时自动调用__enter__
方法,退出时自动调用__exit__
方法。可以通过重写这两个方法来重写上下文管理器。
当进入with语句体时候,会默认自动调用__enter__
,返回值是with语句体绑定的对象
当退出with语句体的时候,会默认调用__exit__
,当with语句体没有异常时,参数全部是None
exc_type:with中产生的异常类型
exc_val:异常对象
exc_tb:异常堆栈轨迹回溯对象
__exit__
方法的返回值None(正常抛出异常,程序中断,等待捕捉异常)
返回值True 镇压异常
```python
class MyManger:
def __enter__(self):
print("进入with语句体")
return "__enter__方法的返回值"
def __exit__(self, exc_type, exc_val, exc_tb):
print(exc_type)
print(exc_val)
print(exc_tb)
print("离开with语句体")
with MyManger() as m:
print("执行with语句")
print(m)
输出结果为:
进入with语句体
执行with语句
__enter__方法的返回值
None
None
None
离开with语句体
当程序正常执行时, exc_type, exc_val, exc_tb
返回值均为None
当程序执行有异常时,执行结果如下:
class MyManger:
def __enter__(self):
print("进入with语句体")
return "__enter__方法的返回值"
def __exit__(self, exc_type, exc_val, exc_tb):
print("exc_type是{}".format(exc_type))
print("=============================")
print("exc_val是{}".format(exc_val))
print("==============================")
print("exc_tb是{}".format(exc_tb))
print("================================")
print("离开with语句体")
with MyManger() as m:
print("执行with语句")
print(m)
raise TypeError("手动抛出的异常")
输出结果为:
Traceback (most recent call last):
进入with语句体
File "E:/new.py", line 18, in <module>
raise TypeError("手动抛出的异常")
执行with语句
__enter__方法的返回值
exc_type是<class 'TypeError'>
TypeError: 手动抛出的异常
=============================
exc_val是手动抛出的异常
==============================
exc_tb是<traceback object at 0x000001DBAAE87208>
================================
离开with语句体
在__exit__
函数中return Ture可以镇压异常,函数不会报错,正常执行。如下所示:
class MyManger:
def __enter__(self):
print("进入with语句体")
return "__enter__方法的返回值"
def __exit__(self, exc_type, exc_val, exc_tb):
print("exc_type是{}".format(exc_type))
print("=============================")
print("exc_val是{}".format(exc_val))
print("==============================")
print("exc_tb是{}".format(exc_tb))
print("================================")
print("离开with语句体")
return True
with MyManger() as m:
print("执行with语句")
print(m)
raise TypeError("手动抛出的异常")
输出:
进入with语句体
执行with语句
__enter__方法的返回值
exc_type是<class 'TypeError'>
=============================
exc_val是手动抛出的异常
==============================
exc_tb是<traceback object at 0x000001E4ABEF7248>
================================
离开with语句体
通过装饰器实现上下文管理器
使用yield作为分界点,
enter方法—yield之前的语句
exit方法----yield之后的内容
enter方法的返回值—yield的产生值—with语句体的绑定对象
from contextlib import contextmanager
@contextmanager
def gen():
print("进入with语句体执行enter")
try:
yield "产生一个值"
except: #跟exit返回Ture是一样的,镇压异常
pass
finally:
print("with离开时执行exit")
with gen() as f:
print(f)
raise TypeError("手动抛出异常")
输出:
进入with语句体执行enter
产生一个值
with离开时执行exit
如果没有except时,异常会报出来,如下:
from contextlib import contextmanager
@contextmanager
def gen():
print("进入with语句体执行enter")
try:
yield "产生一个值"
finally:
print("with离开时执行exit")
with gen() as f:
print(f)
raise TypeError("手动抛出异常")
输出:
Traceback (most recent call last):
File "E:/new.py", line 15, in <module>
raise TypeError("手动抛出异常")
TypeError: 手动抛出异常
进入with语句体执行enter
产生一个值
with离开时执行exit