Python——文件、异常、模块与包
目录
文件相关
文件打开模式
文件读取方法
文件写入方法
异常相关
异常处理的基本结构
异常的分类
捕获异常
异常的传递性
异常处理的高级用法
异常处理的最佳实践
常见的内置异常
自定义异常
异常处理的注意事项
模块相关
模块的基本概念
模块的导入方式
特殊变量
模块的搜索路径
模块的加载机制
模块的重新加载
包的使用
模块的命名空间
模块的文档字符串
模块的初始化代码
文件相关
文件打开模式
- r:只读模式。文件必须存在,否则会报错。
- w:写入模式。如果文件存在,会清空内容;如果文件不存在,会创建新文件。
- a:追加模式。如果文件存在,会在文件末尾追加内容;如果文件不存在,会创建新文件。
- x:独占写模式。如果文件存在,会报错;如果文件不存在,会创建新文件。
- b:二进制模式。用于读写二进制文件,如图片、视频等。
- +:更新模式。用于读写文件,结合其他模式使用,如 r+、w+、a+。
文件读取方法
- read():读取文件的全部内容,返回一个字符串。
- read(size):读取指定数量的字符(或字节,如果是二进制模式)。
- readlines():读取文件的所有行,返回一个列表,每行是一个字符串。
- readline():读取文件的一行,返回一个字符串。
- for line in f:逐行读取文件内容,适合处理大文件,不会占用大量内存。
文件写入方法
- write():写入字符串内容。写入的内容会积攒在程序的内存中(缓冲区),直到调用 flush() 或关闭文件时才会真正写入文件。
- writelines():写入一个字符串列表。列表中的每个元素都会被写入文件,但不会自动添加换行符。
文件关闭
- close():关闭文件,释放文件资源。如果文件已关闭,再次调用 close() 不会报错。
- with open():上下文管理器,自动管理文件的打开和关闭,代码更简洁。
文件指针
- 文件指针表示文件当前的读写位置。
- f.tell():获取当前文件指针的位置。
- f.seek(offset, whence):移动文件指针。
- offset:偏移量。
- whence:
- 0:从文件开头开始计算(默认值)。
- 1:从当前位置开始计算。
- 2:从文件末尾开始计算。
文件编码
- 文件编码指定文件中字符的编码方式。
- 常见的编码方式:
- utf-8:支持多种字符,包括非 ASCII 字符(如中文)。
- ascii:仅支持 ASCII 字符。
- gbk:中文操作系统常用的编码方式。
文件操作中的异常处理
- 文件操作可能会抛出异常,如 FileNotFoundError、PermissionError、IOError 等。
- 使用 try-except 块可以捕获并处理这些异常。
文件操作的应用
- 统计字数:
- 使用 count() 方法统计某个单词的出现次数。
- 使用 for 循环逐行读取文件内容,统计单词的出现次数。
- 文件内容的修改:
- 读取文件内容,修改后再写入文件。
- 文件内容的排序:
- 读取文件内容,排序后再写入文件。
文件操作的注意事项
- 确保文件路径正确,否则可能会报错。
- 在写入文件时,注意文件的编码方式,避免出现编码错误。
- 使用 with open() 语句可以自动管理文件的打开和关闭,避免忘记关闭文件。
- 在处理大文件时,逐行读取文件内容可以避免占用大量内存。
import time
'''
文件操作:打开、读写、关闭
'''
'''
1.open()函数
open(name,mode,encoding)
mode:r:只读w:写入 ,文件存在时会清空内容a:追加
'''
f=open("file.txt","r",encoding="UTF-8")
print(type(f)) # 文件_io.TextIOWrapper类型
'''
2.读取文件
read()
readlines()
readline()
for循环读取行
'''
readf1=f.read()
print((type(readf1))) # 字符串str类型
print(readf1)
readf2=f.read(2) # 此时输出为空,因为文件指针已经在末尾,返回空字符串
print(readf2)
with open('file.txt', 'r') as f:readf2 = f.read(5)print(readf2)# with 语句可以自动管理文件的打开和关闭f=open("file.txt","r",encoding="UTF-8")
readlinesf=f.readlines()
print(type(readlinesf)) # 列表list类型
print(readlinesf)f=open("file.txt","r",encoding="UTF-8")
readlinef=f.readline()
print(type(readlinef)) # 字符串str类型
print(readlinef)#for循环读取行
f=open("file.txt","r",encoding="UTF-8")
for line in f:print(line) #换行也被读取为一个空行'''
文件的写入:
write() 内容积攒在程序的内存中(缓冲区)
writelines()
flush() 内容真正写入文件 f.close()内置了flush的内容
'''
f=open("file.txt","w",encoding="UTF-8")
f.write("hello world!\n")
f.write("hello python!\n")
f.flush()
#writelines()
lines = ["Appending new line 1.\n","Appending new line 2.\n"
]
with open("file.txt", "a", encoding="utf-8") as f:f.writelines(lines)'''
文件指针操作
seek(offset,whence)移动指针
tell()输出指针位置
'''
f=open("file.txt","rb") #需要二进制模式,二进制模式不能指定编码方式
f.seek(-10, 2) # 从文件末尾向前移动5个字符
print(f.tell()) # 输出文件指针的位置
content = f.read() # 从当前位置读取到文件末尾
print(content) # 输出读取的内容'''
关闭文件对象 close()
'''
f.close()
time.sleep(5) #暂停(s)'''
with open() as f 语法操作
'''
with open("file.txt","a",encoding="utf-8") as f:f.write("\nAppending new line.\n") #追加内容'''
应用:统计字数
'''
#1.count()
f=open("file.txt","r",encoding="UTF-8")
content=f.read()
cn=content.count("hello")
print(f"hello出现了{cn}次")
f.close()
#2.for循环
f=open("file.txt","r",encoding="UTF-8")
cn=0
for line in f:line=line.strip()words=line.split(" ")for word in words:if word == "hello":cn+=1
print(f"hello出现了{cn}次")
异常相关
异常处理的基本结构
- try:尝试执行的代码块,可能会引发异常。
- except:捕获并处理异常。可以指定捕获特定类型的异常,也可以捕获所有异常。
- else(可选):如果没有异常发生,执行 else 块中的代码。
- finally(可选):无论是否发生异常,都会执行 finally 块中的代码。常用于清理资源,如关闭文件。
异常的分类
- 内置异常:Python 提供的异常类型,如 NameError、ZeroDivisionError、FileNotFoundError 等。
- 自定义异常:可以通过继承 Exception 类来定义自己的异常类型。
捕获异常
- 捕获所有异常:
- 使用 except 或 except Exception as e 捕获所有异常。
- Exception 是所有内置异常的顶级父类。
- 捕获指定异常:
- 使用 except SpecificException as e 捕获特定类型的异常。
- 捕获多个异常:
- 使用元组 (Exception1, Exception2) 捕获多个异常。
异常的传递性
- 如果在 try 块中发生异常,且没有在当前 try-except 块中被捕获,异常会向上抛,直到被捕获或程序终止。
- 可以在函数中使用 try-except 捕获异常,也可以在调用函数的地方捕获异常。
异常处理的高级用法
- raise:用于手动抛出异常。
- 可以抛出内置异常,也可以抛出自定义异常。
- assert:用于断言,如果条件为 False,会抛出 AssertionError。
- try-except-else-finally 的组合:
- try:尝试执行的代码。
- except:捕获并处理异常。
- else:如果没有异常发生,执行的代码。
- finally:无论是否发生异常,都会执行的代码。
异常处理的最佳实践
- 明确捕获特定异常:尽量捕获特定的异常,而不是捕获所有异常,这样可以更精确地处理问题。
- 记录异常信息:在捕获异常时,可以使用 logging 模块记录异常信息,便于调试和维护。
- 清理资源:在 finally 块中清理资源,如关闭文件、释放网络连接等。
- 避免过度捕获:不要捕获那些无法处理的异常,让异常向上抛,由更上层的代码来处理。
常见的内置异常
- NameError:尝试访问一个未定义的变量时引发。
- ZeroDivisionError:除数为零时引发。
- FileNotFoundError:尝试打开一个不存在的文件时引发。
- TypeError:操作或函数应用于不适当类型的对象时引发。
- ValueError:操作或函数的参数值不合适时引发。
- IndexError:尝试访问序列中不存在的索引时引发。
- KeyError:尝试访问字典中不存在的键时引发。
自定义异常
- 通过继承 Exception 类来定义自己的异常类型。
- 示例:
class MyCustomError(Exception):
pass
异常处理的注意事项
- 异常处理的性能:异常处理会带来一定的性能开销,因此不要滥用异常处理来控制程序流程。
- 异常的链式调用:在捕获异常后,可以重新抛出异常,形成异常链,便于调试和维护。
- 异常的上下文管理:使用 with 语句可以自动管理资源,减少异常处理的复杂性。
'''
捕获异常:
try:
except:
else:(可选)
finally(可选) ————无论如何都要执行,不管有没有异常
'''
#基本捕获异常——(捕获所有异常)
#except (两种写法效果一样)
#except Exception as e (Exception顶级异常)
try:f=open("except.txt","r", encoding="UTF-8")
except:print("NO SuchFile ERROR\nThen open with w mode\n")f=open("except.txt","w",encoding="UTF-8")f.write("Solved a NoSuchFile Exception")
else:print("there is no exception")
finally:f.close()#捕获指定异常
try:print(name)#1/0 #不会被捕获
except NameError as e:print("变量未定义异常")print(e)#捕获多个异常 (,)元组
try:print(name)1/0 #不会被捕获
except (NameError,ZeroDivisionError) as e:print("变量未定义异常")print(e)'''
异常的传递性
'''
def func1():print("func1 start")num=1/0print("func1 end")def func2():print("func2 start")func1()print("func2 end")try:func2()
except ZeroDivisionError as e:print("Occur exception\n",e)
模块相关
模块的基本概念
- 模块:模块是包含 Python 代码的文件,通常以 .py 为扩展名。模块可以包含函数、类、变量等定义,用于组织和重用代码。
- 包:包是一种特殊的模块,用于组织多个模块。包通常包含一个 __init__.py 文件,该文件可以为空,也可以包含初始化代码。
模块的导入方式
- 直接导入模块:
import module_name
使用 module_name.function_name 或 module_name.class_name 来访问模块中的内容。
- 导入模块中的特定内容:
from module_name import function_name, class_name
直接使用 function_name 或 class_name 来访问。
- 导入模块并重命名:
import module_name as new_name
使用 new_name.function_name 来访问。
- 导入包中的模块:
from package_name import module_name
使用 module_name.function_name 来访问。
特殊变量
- __main__:
- 当模块被直接运行时,__name__ 的值为 "__main__"。
- 当模块被导入时,__name__ 的值为模块名。
- 常用于判断模块是被直接运行还是被导入,从而决定是否执行某些代码。
- 示例:
if __name__ == "__main__":
print("This module is being run directly")
else:
print("This module is being imported")
- __all__:
- 定义在模块中,用于指定从模块中导入时,from module_name import * 可以导入的成员。
- 如果未定义 __all__,则导入所有不以下划线开头的成员。
- 示例:
__all__ = ["function1", "class1"]
模块的搜索路径
- Python 解释器在导入模块时,会按照以下顺序搜索模块:
- 当前目录。
- 环境变量 PYTHONPATH 中指定的路径。
- 安装的 Python 库的路径。
- 可以通过 sys.path 查看模块的搜索路径:
import sys
print(sys.path)
模块的加载机制
- 当导入模块时,Python 会先检查是否已经加载了该模块。如果已加载,则直接使用已加载的模块,不会重新加载。
- 如果未加载,则会搜索模块文件,加载并执行模块代码。
模块的重新加载
- 可以使用 importlib.reload() 重新加载模块,但需要注意重新加载可能会导致一些问题,如已创建的对象不会自动更新为新模块中的定义。
- 示例:
import importlib
importlib.reload(module_name)
包的使用
- 包是一种特殊的模块,用于组织多个模块。
- 包通常包含一个 __init__.py 文件,该文件可以为空,也可以包含初始化代码。
- 示例包结构:
my_package/
__init__.py 【只有它存在才是包】
module1.py
module2.py
- 导入包中的模块:
from my_package import module1
模块的命名空间
- 每个模块都有自己的命名空间,模块中的变量、函数、类等定义不会与其他模块冲突。
- 可以通过模块名来访问模块中的内容,避免命名冲突。
模块的文档字符串
- 模块的文档字符串是模块的第一行字符串,用于描述模块的功能和使用方法。
- 示例:
"""
This is a module for demonstrating module concepts.
"""
模块的初始化代码
模块中的代码在导入时会自动执行,可以用于初始化模块。