Python 文件 I/O
Python 文件 I/O
Section titled “Python 文件 I/O”本章将介绍 Python 中基本的输入/输出 (I/O) 操作,重点是与控制台(标准输入/输出)和文件进行交互。
屏幕输出 (Printing)
Section titled “屏幕输出 (Printing)”print() 函数是将输出内容显示到标准输出(通常是控制台)的主要方式。你可以传递零个或多个对象进行打印,对象之间用逗号分隔。
# 简单打印print("Hello, Python!")
# 打印多个项(默认用空格分隔)name = "Alice"age = 30print("Name:", name, "Age:", age)
# 使用 f-strings 进行格式化输出(推荐)print(f"Name: {name}, Age: {age}")
# 控制分隔符和结束符print("Item 1", "Item 2", sep=" | ") # 自定义分隔符print("First line", end=" - ") # 自定义结束符(默认为 '\n',即换行符)print("Second line")运行以上代码,会产生以下结果:
Hello, Python!Name: Alice Age: 30Name: Alice, Age: 30Item 1 | Item 2First line - Second line读取键盘输入
Section titled “读取键盘输入”Python 提供了内置的 input() 函数来从标准输入(通常是键盘)读取一行文本。
input() 函数
Section titled “input() 函数”input([prompt]) 函数会显示可选的 prompt 字符串,等待用户输入文本并按回车键,然后将输入的文本以字符串的形式返回。
#!/usr/bin/env python3
user_name = input("Enter your name: ") # 显示提示信息并等待用户输入print(f"Hello, {user_name}!")
# input() 的返回值总是字符串,如果需要,请进行转换age_str = input("Enter your age: ")try: age_int = int(age_str) # 尝试将字符串转换为整数 print(f"You will be {age_int + 1} next year.")except ValueError: # 如果转换失败(输入的不是有效数字) print("Invalid age entered. Please enter a number.")运行此脚本可能看起来像这样:
Enter your name: BobHello, Bob!Enter your age: 25You will be 26 next year.注意:Python 2 中的 raw_input() 函数在 Python 3 中已被 input() 函数取代。旧的 Python 2 中的 input() (它会评估输入表达式) 已被移除。
打开和关闭文件
Section titled “打开和关闭文件”Python 提供了内置函数和方法来进行文件操作。
open() 函数和 with 语句
Section titled “open() 函数和 with 语句”在读写文件之前,必须使用 open() 函数打开文件。强烈推荐的方式是使用 with 语句,因为它能确保文件在使用后自动关闭,即使发生错误也不例外。
with open(file_path, mode='r', encoding=None) as file_object: # 在此处使用 file_object 进行文件操作 pass # 退出 'with' 代码块时,文件会自动关闭参数详情:
file_path: 包含文件路径的字符串。mode: 决定文件打开的方式(例如,‘r’ 用于读取,‘w’ 用于写入,‘a’ 用于追加,‘b’ 用于二进制,’+’ 用于更新)。默认为'r'(读取文本)。encoding: 指定文本编码(例如,'utf-8','ascii')。对于文本文件至关重要,确保在不同系统上正确解释字符。对于文本文件,始终指定编码。'utf-8'是一种常见且安全的选择。- 还存在缓冲选项,但通常不需要更改。
文件模式详情:
| 模式 | 描述 |
|---|---|
r | 读取(默认)。如果文件未找到则报错。 |
rb | 以二进制模式读取。 |
r+ | 读写。指针位于开头。如果文件未找到则报错。 |
rb+ | 以二进制模式读写。指针位于开头。 |
w | 写入。创建文件或截断(清空)现有文件。 |
wb | 以二进制模式写入。创建或截断。 |
w+ | 写入并读取。创建或截断。 |
wb+ | 以二进制模式写入并读取。创建或截断。 |
a | 追加。如果文件未找到则创建。指针位于末尾。 |
ab | 以二进制模式追加。如果文件未找到则创建。指针位于末尾。 |
a+ | 追加并读取。如果文件未找到则创建。写入时指针位于末尾。 |
ab+ | 以二进制模式追加并读取。如果文件未找到则创建。写入时指针位于末尾。 |
x | 独占创建。如果文件已存在则报错。 |
xb | 以二进制模式独占创建。 |
x+ | 独占创建,并读写。 |
xb+ | 以二进制模式独占创建,并读写。 |
文件对象属性
Section titled “文件对象属性”open() 函数返回的文件对象具有几个有用的属性:
| 属性 | 描述 |
|---|---|
file.closed | 一个布尔值,指示文件是否已关闭。 |
file.mode | 打开文件时使用的模式。 |
file.name | 文件名。 |
file.encoding | 文件使用的编码(用于文本模式)。 |
#!/usr/bin/env python3
file_path = "sample.txt"
# 以写入模式打开文件(创建或覆盖)try: with open(file_path, "w", encoding="utf-8") as f: print(f"Name of the file: {f.name}") # 打印文件名属性 print(f"Closed or not : {f.closed}") # 打印 closed 属性,在 with 块内为 False print(f"Opening mode : {f.mode}") # 打印 mode 属性 print(f"Encoding : {f.encoding}") # 打印 encoding 属性 f.write("This is a sample line.\n") # 写入一行文本 # 退出 'with' 代码块后 print(f"\nFile closed now? {f.closed}") # 注意:f 变量仍然存在,但文件已关闭
except IOError as e: # 捕获 IOError 异常 print(f"Error opening or writing file: {e}")运行此代码会产生类似于以下结果:
Name of the file: sample.txtClosed or not : FalseOpening mode : wEncoding : utf-8
File closed now? Trueclose() 方法(以及为何 with 更好)
Section titled “close() 方法(以及为何 with 更好)”文件对象有一个 close() 方法。如果你不使用 with 语句打开文件,则必须显式调用 close() 来确保数据写入磁盘并释放资源。然而,忘记关闭或在关闭前遇到错误可能导致问题。
手动关闭(不推荐):
# 手动打开/关闭 - 尽可能避免使用f = None # 初始化为 Nonetry: f = open("old_style.txt", "w", encoding="utf-8") # 打开文件 print(f"File name: {f.name}") f.write("Manual close example.\n") # 写入数据finally: # 无论是否发生异常,都会执行 finally 块 if f: # 检查文件对象是否存在 f.close() # 必须确保调用 close() 方法 print("File closed manually.")使用 with 语句是现代 Python 中标准且最安全的做法。
读取和写入文件
Section titled “读取和写入文件”文件对象提供了用于读取和写入数据的方法。
write() 方法
Section titled “write() 方法”将字符串(在文本模式下)或字节(在二进制模式下)写入文件。它不会自动添加换行符 (\n)。返回写入的字符或字节数。
file_object.write(data)#!/usr/bin/env python3
file_path = "output.txt"
try: with open(file_path, "w", encoding="utf-8") as f: # 以写入模式打开文件 num_chars = f.write("Python is a great language.\n") # 写入第一行并获取写入字符数 print(f"Wrote {num_chars} characters.") # 打印写入字符数 f.write("Yes, it's great!!\n") # 写入第二行 print(f"Successfully wrote to {file_path}") # 打印成功信息except IOError as e: # 捕获 IOError 异常 print(f"Error writing file: {e}")
# output.txt 文件的内容将是:# Python is a great language.# Yes, it's great!!read() 方法
Section titled “read() 方法”从文件中读取数据。在文本模式下读取字符;在二进制模式下读取字节。
file_object.read(size=-1)这里,size 是可选的要读取的字符或字节数。如果省略或为负数,则读取直到文件末尾 (EOF)。
示例(使用上面创建的 output.txt)
Section titled “示例(使用上面创建的 output.txt)”#!/usr/bin/env python3
file_path = "output.txt"
try: with open(file_path, "r", encoding="utf-8") as f: # 以读取模式打开文件 # 读取前 10 个字符 first_part = f.read(10) print(f"First 10 chars: '{first_part}'")
# 读取文件的其余部分 rest_of_file = f.read() # read() 再次调用会从当前位置开始读取 print(f"Rest of file: '{rest_of_file}'")
print("\nReading entire file at once:") with open(file_path, "r", encoding="utf-8") as f: # 再次打开文件以从头开始读取 all_content = f.read() # 读取整个文件内容 print(f"'{all_content}'")
except FileNotFoundError: # 捕获文件未找到异常 print(f"Error: File '{file_path}' not found.")except IOError as e: # 捕获 IOError 异常 print(f"Error reading file: {e}")运行此代码会产生以下结果:
First 10 chars: 'Python is 'Rest of file: 'a great language.\nYes, it's great!!\n'
Reading entire file at once:'Python is a great language.\nYes, it's great!!\n'其他读取方法:
Section titled “其他读取方法:”readline(): 读取一行,包括末尾的\n(或直到 EOF)。readlines(): 将所有行读取到一个字符串列表中,每行包含其末尾的\n。
示例(逐行读取):
Section titled “示例(逐行读取):”print("\nReading with readline():")try: with open(file_path, "r", encoding="utf-8") as f: line1 = f.readline() # 读取第一行 line2 = f.readline() # 读取第二行 print(f"Line 1: {line1.strip()}") # .strip() 移除行首/行尾的空白字符 print(f"Line 2: {line2.strip()}")except FileNotFoundError: print(f"Error: File '{file_path}' not found.")文件位置 (seek 和 tell)
Section titled “文件位置 (seek 和 tell)”tell(): 返回文件指针的当前位置(从文件开头算起的字节偏移量)。
seek(offset, whence=0): 移动文件指针。offset 是要移动的字节数。whence 确定参照点:
0(默认): 从文件开头算起的绝对位置。1: 从当前指针位置算起的相对位置。2: 从文件末尾算起的相对位置(偏移量offset通常为负数)。
#!/usr/bin/env python3
file_path = "output.txt"
try: with open(file_path, "r+", encoding="utf-8") as f: # 以读写模式打开文件 # 读取前 10 个字符 str_data = f.read(10) print(f"Read String is : '{str_data}'")
# 检查当前位置 position = f.tell() # 获取当前指针位置 print(f"Current file position : {position}")
# 将指针重新定位到开头 f.seek(0, 0) # 将指针移动到文件开头 (0 偏移量,从开头算起) str_data = f.read(10) # 再次读取 print(f"Again read String is : '{str_data}'")
# 移动到末尾并写入 f.seek(0, 2) # 将指针移动到文件末尾 (0 偏移量,从末尾算起) f.write("Appending using seek.\n") # 在末尾写入数据
except FileNotFoundError: print(f"Error: File '{file_path}' not found.")except IOError as e: print(f"Error accessing file: {e}")运行此代码会产生以下结果:
Read String is : 'Python is 'Current file position : 10Again read String is : 'Python is '文件系统操作 (os 和 pathlib)
Section titled “文件系统操作 (os 和 pathlib)”os 和 pathlib 等模块提供了除读写文件内容之外的文件系统任务函数。
提供了一种平台无关的方式来与操作系统交互。
重命名文件:os.rename(current_name, new_name)
Section titled “重命名文件:os.rename(current_name, new_name)”import os
# 先创建一个临时文件with open("test1.txt", "w") as f: f.write("dummy")
try: os.rename("test1.txt", "test2.txt") # 将 test1.txt 重命名为 test2.txt print("Renamed test1.txt to test2.txt")except OSError as e: # 捕获操作系统相关的错误 print(f"Error renaming file: {e}")移除文件:os.remove(file_name) 或 os.unlink(file_name)
Section titled “移除文件:os.remove(file_name) 或 os.unlink(file_name)”try: os.remove("test2.txt") # 移除 test2.txt 文件 print("Removed test2.txt")except OSError as e: print(f"Error removing file: {e}")pathlib 模块(现代方法)
Section titled “pathlib 模块(现代方法)”提供了文件路径的面向对象接口,通常能使代码更具可读性。
from pathlib import Path
# 创建一个临时文件dummy_file = Path("pathlib_test1.txt") # 创建一个 Path 对象dummy_file.write_text("dummy content", encoding="utf-8") # 使用 Path 对象写入文本
new_file_path = Path("pathlib_test2.txt")new_dir_path = Path("my_test_dir")
# 重命名try: dummy_file.rename(new_file_path) # 使用 Path 对象的 rename 方法 print(f"Renamed {dummy_file} to {new_file_path}")except OSError as e: print(f"Error renaming: {e}")
# 移除try: new_file_path.unlink() # 对于文件,使用 unlink() 方法 print(f"Removed {new_file_path}")except OSError as e: print(f"Error removing: {e}")
# 创建目录try: new_dir_path.mkdir(exist_ok=True) # 使用 mkdir() 创建目录;exist_ok=True 表示如果目录已存在则不报错 print(f"Created directory {new_dir_path}")except OSError as e: print(f"Error creating directory: {e}")
# 获取当前目录print(f"Current directory: {Path.cwd()}") # 使用 Path.cwd() 获取当前工作目录
# 移除目录(必须是空的)try: new_dir_path.rmdir() # 对于目录,使用 rmdir() 方法 print(f"Removed directory {new_dir_path}")except OSError as e: print(f"Error removing directory (may not be empty): {e}") # 移除非空目录会报错Python 中的目录操作
Section titled “Python 中的目录操作”os 和 pathlib 都提供了管理目录的函数。
os.mkdir(path) 或 Path(path).mkdir()
os.chdir(path) (改变当前进程的当前工作目录)
获取当前目录:
Section titled “获取当前目录:”os.getcwd() 或 Path.cwd()
os.rmdir(path) 或 Path(path).rmdir() (目录必须是空的)
要移除包含内容的目录,请使用 shutil.rmtree(path)(小心使用!)。
文件和目录工具总结
Section titled “文件和目录工具总结”- 内置函数
open(): 用于读写文件内容(结合with语句使用)。 os模块: 传统的、基于函数的方法,用于操作系统交互(路径、进程)。os.path子模块用于路径操作。pathlib模块: 现代的、面向对象的方法,用于路径操作和基本文件操作。通常更受青睐。shutil模块: 用于更高级的文件操作(复制、移动、移除目录树)。