Python的文件操作
- 文件的打开与关闭
- 文件的读取与写入
文件的打开
- 内置函数:open(文件名, 模式)
- os模块的函数:os.open(文件名, 模式)
- with open(文件名, 模式) as file
文件的关闭
- fileobject.close()
fileobject是文件对象
- os.close(file)
关闭文件
1 | file_1 = open('F:\\file_1.txt', 'r') |
默认的文件编码encoding一般依赖于系统的区域设置和Python的版本。
cp936
代表GBK编码
标准编码参考:https://docs.python.org/3/library/codecs.html
1 | import io #io.open()是内置函数open的别名,本质是一样的 |
1 | import os |
区别:
open()
函数返回的是一个文件对象,而os.open()
函数返回的是一个文件描述符(即整数)。python
内置的open()
函数主要用于处理文本文件,而os.open()
函数主要用于处理二进制文件和低级文件操作。
使用with语句即python的上下文管理器,它可以自动关闭文件,而用open()函数则需要手动关闭文件。
1 | with open('F:\\file_1.txt', 'rb+') as f: |
文件的打开模式
- ‘r’:只读模式
- ‘w’:覆盖写模式,不存在则创建,存在则完全覆盖
- ‘a’:追加写模式,不存在则创建,存在则在文件最后追加内容
- ‘x’:排他性创建模式:如果文件不存在,创建并打开写模式的文件。如果文件已存在,操作将失败。
- ‘b’:二进制文件模式
- ‘+’:在原功能基础上增加同时读写功能,可与r/w/a组合。
思考下列代码分别属于什么打开模式:
- open(‘file.txt’, ‘w’) 写入模式
- open(‘file.txt’, ‘w+’) 读写模式
- open(‘file.txt’, ‘rb’) 二进制读取模式
- open(‘file.txt’, ‘rb+’) 二进制读写模式
文件的读取与写入
- read()读取文件内容
- readline()返回文件的一行内容,格式为字符串
- readlines()返回文件所有行内容,格式为列表
- write()写入文件内容
- writelines()将一个字符串列表写入文件
1 | #read()读取文件内容 |
1 | #readline()读取一行内容 |
1 | #readlines()逐行读整个文件内容,包括换行符 |
1 | # w覆盖写入,write()参数必须为字符串,如果想换行,必须加上换行符\n |
1 | # 写入字符串列表,如果想换行,必须加上换行符\n |
绝对路径和相对路径
- 绝对路径是从根目录开始的完整路径。它提供了到达指定文件或目录的具体位置,不依赖于当前工作目录的位置。
系统中的绝对路径E:\jupyter\python
,python中的绝对路径r"E:\jupyter\python"
或者E:/jupyter/python
或者E:\\jupyter\\open
- 相对路径是相对于当前工作目录的路径。它通过相对位置来指定文件或目录,简化了路径的表达,但其具体位置依赖于当前的工作目录。
os模块常用的路径操作
获取当前路径名
1
2
3
4#1.获取当前路径名
import os
print(os.getcwd())
print(os.path.abspath(os.curdir)) #返回绝对路径 os.path.abspath获取父目录路径名
1
2print(os.path.dirname('../python/6.1 Python的文件操作.ipynb'))
print(os.path.dirname(os.path.join('../', 'open', 'op', 'file.txt')))返回指定路径下的文件和目录列表
1
2
3#3. 返回指定路径下的文件和目录列表
#'.'或'./'代表当前路径 #'..'或'../'代表上一级路径
print(os.listdir('..'))创建目录
1
2#4.在当前文件夹下创建单层目录
os.mkdir('new1123')合并两个或多个路径名组件
1
2
3
4
5
6
7
8
9
10
11import os
#5. 合并两个或多个路径名组件
print(os.path.join('../', 'open'))
#合并一个没有的目录,需要重新创建目录
# os.mkdir(os.path.join('../', 'open'))
print(os.path.join('../', 'open','./', 'file.txt'))
with open('new1123', 'w') as fs:
fs.write('111222333')统一规范化路径分隔符
1
2
3
4
5
6#6.统一规范化路径分隔符
file_op = os.path.join('../', 'open','./' , 'file.txt')
uni_op = file_op.replace(os.sep, '/') #直接对字符串进行替换
normalized_path = os.path.normpath(file_op) #用方法规范化
print(uni_op)
print(normalized_path)判断文件是否存在
1
2
3
4
5#7.判断文件是否存在
if os.path.exists('F:\\file_2.txt'):
print('yes')
else:
print('no')
更多的os操作请查看官方文档:https://docs.python.org/3/library/os.html#module-os
csv格式文件的读取和写入
csv是逗号分隔符文本格式,常用于Excel和数据库的数据导入和导出。
csv的读取:
csv.reader(csvfile, dialect='excel', **fmtparams)
#csvfile文件对象;dialect指定csv格式;fmtparams用于指定特定格式覆盖dialect的格式csv.reader()创建的是可迭代对象
1 | #csv的读取 |
- csv的写入:
csv.writer(csvfile, dialect='excel', **fmtparams)
csv文件.writerow(row)
#写入一行csv文件.writerows(rows)
#写入多行
1 | header = ['id', 'name', 'sex', 'work'] |
在Windows上的换行符为\r\n
,而在Linux和MacOS上的换行符为\n
。
open()中有个参数’newline’控制如何处理换行符。
可令newline=''
此参数在不同操作系统间提供一致的换行符处理,避免了跨平台文本文件处理中的问题。
newline参数只对文本模式有效,对二进制模式无效。
1 | header = ['id', 'name', 'sex', 'work'] |
读取’green_red’文件夹下的’train’文件夹,然后读取里面的csv文件,把里面的前10行数据放到新的列表中。
1 | import csv |
对象序列化和pickle模块
- 序列化是Python对象转换为数据格式,以便在不同的环境中存储、传输和重建。
- 反序列化是从磁盘文件或所接收到的数据形式恢复,得到相应对象的过程。
- 对象序列化广泛用于各种分布式并行处理系统。
- pickle模块可以实现对象的序列化。
1 | import pickle |
应用实例:
- 将一个整数列表[1, 2, 3, 4, 5]序列化到一个名为numbers.pkl的文件中。
- 从numbers.pkl文件中反序列化该列表,并将其打印出来。
1 | import pickle |
文件的筛选:
- file.endswith() #以…结尾的文件名
- file.startswith() #以…开始的文件名
1 | # 假设我们有一个文件名列表 |
1 | # 假设我们有一个文件名列表 |
Python的异常捕获
错误与异常
错误
错误(Error)可以分为语法错误和逻辑错误,当运行时出现报错信息,此时就产生了异常(Exception)。
1
2
3
4
5#语法错误在编译阶段就会报错
def op(a):
a = 1
list([1,2,3)
异常
- 程序运行时检测到的错误称为异常,异常不一定导致严重的后果,而是显示错误信息。
Python中常见的异常
更多的内置异常类请参考官方文档:https://docs.python.org/3/library/exceptions.html#index-2
NameError
:尝试访问一个未声明的变量ZeroDivisionError
:除数为0SyntaxError
:解释器语法错误IndexError
:请求的索引超出序列范围TypeError
:类型错误KeyError
:请求一个不存在的字典键FileNotFoundError
:请求不存在的文件或目录时FileExistsError
:创建一个已经存在的文件或目录时
异常处理
try-except
语句
1 | try: |
首先,执行 try 子句,如果没有触发异常,则跳过 except 子句,try 语句执行完毕。
如果在执行 try 子句时发生了异常,则跳过该子句中剩下的部分。判断异常类型与 except 指定的异常是否匹配,若匹配则会执行 except 子句。若不匹配,异常就会被递交至上一级,也就是由该段代码的调用者去处理。如果最后还是无法解决的话,就会出现错误,导致程序崩溃。
except可以有不同的异常类型,但最多只有一个处理程序会被执行。第一个匹配到的异常类型将被处理,其他匹配到的异常类型将不会被处理。
1 | except (RuntimeError, TypeError, NameError): |
- 如果想要处理所有匹配到的异常类型,并且在每个异常类型中执行不同的代码,可以使用多个except语句,每个语句处理一个特定的异常类型。
1 | try: |
1 | try: |
2.try-except-else
语句
1 | try: |
1 | def divide(x, y): |
try-finally
语句
1 | try: |
try-except-else-finally
语句
1 | try: |
无论异常是否发生,无论异常是否被捕捉到,finally
后的语句块一定会被执行。
1 | #不管try返回了什么值,如果finally中也有返回值,则最终返回finally的。 |
1 | #如果try语句要执行break、continue或return语句,finally子句将在break、continue或return语句执行之前执行 |
1 | #如果try发生异常,执行完finally语句后,会重新抛出异常 |
1 | #如果finally子句执行break、continue或return语句,则不会重新引发异常 |
抛出异常
- 根据程序的运行状态或满足的条件,主动引发一个指定的异常,而不是等待Python解释器在执行过程中遇到错误时自动抛出异常。
- 使用raise语句抛出异常,此异常可以是
BaseException
的子类、由BaseException
派生的自定义类或异常类的实例。 - 直接使用异常类
raise ValueError
;派生Exception类的自定义异常类class MyError(Exception): pass; raise MyError
;使用异常类的实例raise ValueError('输入值有误')
;
1 | try: |
异常链
- Python中的异常链是指显式地将异常链接在一起,将一个异常链接到另一个异常的能力。当一个异常作为另一个异常的直接后果而发生时,这个特性特别有用。通过链接异常,开发人员可以提供更多的上下文和更清晰的回溯,从而更容易调试。
- 用from语句链接异常,并与raise语句合用形成基本结构:
raise NewException from exception
。 - 在某些情况下,不想关注其他异常,可以使用
from None
。
捕获所有类型的异常
BaseException
是所有异常的公共基类。BaseException
的一个子类Exception
是所有非致命异常的基类,所有内置的、非系统退出的异常都派生自这个类。所有用户定义的异常也从这个类派生。SystemExit
、KeyboardInterrupt
是用户希望中断程序时的异常;GeneratorExit
是生成器或协议中断时的异常。- 处理异常最常见的模式是 打印 或 记录异常。
捕获BaseException可能会意外地捕获到SystemExit和KeyboardInterrupt等异常,这可能会导致程序在应该正常退出或响应用户中断的情况下继续运行。Exception确保不阻碍正常的程序退出,也能专注于处理程序中可能发生的错误。
所以通常情况下我们使用Exception
去捕获几乎所有的异常情况。
使用Exception
捕获异常时,通常后面加一个异常参数e(也可以是其他的变量名),它用于打印异常的具体细节。
文件读取与异常捕获实例:
编写一个Python脚本,尝试读取一个不存在的文件。
使用try-except语句捕获并处理FileNotFoundError异常。
使用else子句打印一条成功读取文件的消息。
使用finally子句确保文件被正确关闭。
1 | try: |