Python 03_Python读写文件操作

一、Python中文件IO操作

1.1 IO简介

IO 即 input 与 output ,数据就如水流在水管中流向磁盘(类似队列,先进先出)。

Python解释器在运行.py文件时用到操作系统(OS)及其资源,.py文件里的代码就是通过调用操作系统提供的系统调用函数来操作磁盘上的文件(即读写磁盘里的文件)。

1.2 open 函数(创建并)打开文件 和 close 方法关闭文件

在进行文件读写之前,有个重要的步骤——将文件打开,同时指定针对文件的读写模式,比如只读、只写、可读可写等等。只有先打开文件才能对文件进行读写操作。

打开文件使用内置函数 open(), 该函数常用参数 有 filemodeencoding

  • file: 指定打开的文件路径
  • mode: 指定打开文件的读写模式,默认为只读打开,其中,读写模式 有以下常用选项:
    • r:只读,若文件不存在则抛出 FileNotFoundError 异常
    • w:只写,将覆盖所有原有内容,若文件不存在则创建文件
    • a:只写,以追加(append)的形式写入内容,若文件不存在则创建文件
    • r+:可读可写,若文件不存在则抛出 FileNotFoundError 异常
    • w+:可读可写,若文件不存在则创建文件
    • a+:可读可写,写入时使用追加(append)模式,若文件不存在则创建文件
    • 以上所有读写模式都是基于文本内容的,如果想要读写二进制内容,可在上面的基础上添加 b 模式,如 rbwb+
  • encoding:指定打开文件的编码方式,处理非英文文本时(编码错误是常客)记住设置正确的编码格式,如: open('file.txt', 'r', encoding='utf-8')

关闭文件 使用 文件句柄的 close 方法,无需传送任何参数。

使用方式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 方式一:
f = open(file='文件路径', mode='a+', encoding='utf-8')

# TODO:操作(读写)文件

# 每次打开文件后,无论进行了多少读写操作,最终都一定要将文件关闭,
# 因为打开文件会消耗相关系统资源(文件描述符),不使用时应及时释放。
f.close()


# 方式二:
# open() 后的 file 对象会被 as 关键字赋予变量 f。和之前一样,我们利用 f 进行文件读写。
# with 语句会在它的代码块执行完毕后,或代码块抛出异常时,自动关闭文件,为我们省却了 f.close() 步骤。
with open('example.txt', 'r') as file:
    content = file.read()
print(content)

Tips: with 语句不仅简洁,还能自动关闭文件,防止资源泄露。

  • with xxx as name:

with可以管理上下文资源,无论什么原因跳出(结束)该模块,系统资源都将自动关闭,达到释放资源的目的。

这里的xxx称为上下文表达式,结果为上下文管理器

解释:一个类对象实现了__enter__()__exit__()方法,则这个类对象遵守了上下文协议,该类的实例对象就是上下文管理器,如 open() 创建的 file 句柄 对象就是上下文管理器,with 缩进内的都为 with 语句体

执行的顺序:调用执行__enter__()方法 –> 调用执行 with 语句体 –> 调用执行__exit__()方法,无论是否产生异常都会调用两个方法,__exit__()进行退出后会自动关闭资源

Tips: 文本文件常用的打开模式 mode 如下

模式 描述
t 文本模式(默认)
x 写模式,新建一个文件
b 二进制模式,打开二进制文件
+ 更新一个文件(可读可写)
r 以只读模式打开一个文件
rb 以二进制格式只读模式打开一个文件
w 打开一个文件进行写入,如果文件内容已存在,会清除原有的内容
wb 以二进制格式只写模式打开一个文件,会清除原有的内容
a 打开一个文件并追加内容,会往文件尾部添加内容
ab 以二进制格式打开一个文件并追加内容,会往文件尾部添加内容
w+ 打开一个文件进行读写,如果文件内容已存在,会清除原有的内容
a+ 打开一个文件并使用追加进行读写

1.3 文件操作简介

  • 读取文件操作
  1. file.read([size=-1]) 方法: 从文件对象(file)流中读取至多 size 个字符并以单个 str 的形式返回。 如果 size 为负值或 None,则读取至 EOF。即一次读取整个文件内容,适合读取小文件,示例如下:
1
2
3
4
content = ""
with open('example.txt', 'r') as file:
    content = file.read()   # 一次读取整个文件内容
print(content)
  1. file.readline([size=-1]) 方法:从文件对象(file)中读取至换行符或 EOF 并返回单个 str。 如果流已经到达 EOF,则将返回一个空字符串。如果指定了 size ,最多将读取 size 个字符。示例如下:
1
2
3
4
# 逐行读取
with open('example1.csv', 'r') as file:
    while (line := file.readline()) != '':
        print(line)
  1. file.readlines([hint=-1]) 方法:从流中读取并返回包含多行的列表。可以指定 hint 来控制要读取的行数:如果(以字节/字符数表示的)所有行的总大小超出了 hint 则将不会读取更多的行。0 或更小的 hint 值以及 None,会被视为没有 hint,则读取至 EOF,以列表的形式返回文件所有的字符串。
1
2
3
4
with open('example.txt', 'r') as file:
    lines = file.readlines()
    for line in lines:
        print(line)
  1. 逐行读取:在不调用 file.readline() 或 file.readlines() 的情况下使用 for line in file: … 来遍历文件对象功能已经实现,示例如下:
1
2
3
with open('large_file.txt', 'r') as file:
    for line in file:   # 逐行读取,既优雅又高效!
        print(line.strip())
  1. 文件迭代器:高效遍历大文件,使用迭代器可以显著提高性能。itertools.islice(file, line) 可以按需读取文件的一部分,避免内存负担,示例如下:
1
2
3
4
5
import itertools

with open('example.txt', 'r') as file:
    for line in itertools.islice(file, 100):
        print(line.strip())
  • 文件写入操作
  1. file.write(buf) 方法:将给定的 字节型对象数据 buf 写入到下层的原始流,并返回所写入的实际字节数。实际写入字节数可以少于 buf 的总字节数,具体取决于下层原始流的设定,调用者可以在此方法返回后释放或改变 buf,因此该实现应该仅在方法调用期间访问 buf。示例如下:
1
2
3
4
s = "Data buffer."
with open('example.txt', 'w+',encoding='utf-8') as file:
    file.write(s)
    file.write('\n')
  1. file.writelines(lines) 方法: 将行列表写入到流。lines 为字符串列表,该方法不会添加行分隔符,因此通常所提供的每一行都带有末尾行分隔符 或 手动添加分割符。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
data = [
    ['Name', 'Age', 'City'],
    ['Alice', '30', 'New York'],
    ['Alice', '30'],
    ['Bob', '25', 'Los, Angeles'],
    ['Bob', '25', 'Los Angeles', '3']
]

with open('example.log', 'w', newline='') as file:
    for line in data:
        file.writelines(line)
        file.write('\n')        # 手动添加 换行符
  • 文件定位操作
  1. file.seek(offset, whence=os.SEEK_SET) 方法: 将流位置修改到给定的字节 offset,它将相对于 whence 所指明的位置进行解析,并返回新的绝对位置。 whence 的常用值有:
  • os.SEEK_SET 或 0 – 流的开头(默认值;offset 应为零或正值
  • os.SEEK_CUR 或 1 – 当前流位置;offset 可以为负值
  • os.SEEK_END 或 2 – 流的末尾;offset 通常为负值

示例:

1
2
3
4
5
with open('example.log', 'a+',encoding='utf-8') as file:
    file.write('Data buffer!')
    file.seek(0)                # 写指针导致读写指针指在最后,重置指针以便于从头读取
    s=file.read(10)             # 读取10个字符
    print(s)
  • JSON 数据交换:使用 json 处理结构化数据,无论是读取还是写入,都能轻松完成数据的序列化和反序列化。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# json 处理 结构化数据
import json

data = {"name": "John", "age": 30}
with open('data.json', 'w') as file:
    json.dump(data, file)   # 系列化 data 后写入 file

# 读取 JSON 文件
with open('data.json', 'r') as file:
    loaded_data = json.load(file) # 读取json数据后返序列化 为 字典
    print(loaded_data)

1.4 其它的文件基础操作

  1. 获取文件大小:利用 os.path.getsize() 函数可以获取文件大小
  2. 文件重命名:利用 os.rename('old_name.txt', 'new_name.txt') 给文件重命名
  3. 文件移动:利用 shutil.move('source.txt', 'destination/') 移动文件
  4. 文件搜索:利用 glob.glob() 对文件进行搜索
  5. 文件列表:利用 os.listdir('dir/name') 列出指定目录下的文件列表
  6. 文件比较:比较两个文件是否相同,difflib 库能帮你找出差异,细微差别也逃不过它的法眼
  7. 文件备份:定期备份文件,使用 shutil.copy()shutil.copy2(),让数据安全无忧。

二、Python 中 csv 文件的写入与读取

2.1 CSV 文件简介

CSV(Comma-Separated Values)即逗号分隔值,是一种以逗号(,)分隔按行存储的简单的文本文件,所有的数据都表现为字符串类型(注意:数字为字符串类型),每一行代表一条数据记录,每条记录可以包含多个字段(相邻字段之间以 逗号 , 分割)。

如果CSV中有中文,应以utf-8编码读写.

在数据处理和数据分析领域,CSV 文件是一种常见的文件格式,被广泛用于表格数据的交换和数据存储。

2.2 Python 中的 csv 模块处理 CSV 文件数据

Python 内置的 csv 模块提供了一系列函数来操作(读写)CSV 文件。它可以处理各种类型的 CSV 数据,包括不同的分隔符和引号约定。

Python 通过内置的 csv 模块提供了对 CSV 文件的读写支持,使得处理这种类型的文件变得简单高效。

  • 写入 CSV 文件

示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 基本用法:
import csv

# 数据
data = [
    ['Name', 'Age', 'City'],
    ['Alice', 30, 'New York'],
    ['Bob', 25, 'Los Angeles'],
    ['Alice', 30],                  # 数据 缺失字段
    ['Bob', 25, 'Los Angeles',3]    # 数据 多出 字段
]

# 写入 CSV 文件
# 语法:`csv.writer(f)`
# writer支持 `writerow(列表)` 单行写入,和 `writerows(嵌套列表)` 批量写入多行,无须手动保存。
with open('example.csv', 'w', newline='') as file:
    writer = csv.writer(file)
    writer.writerows(data)  # 数据 缺失、多出 字段 均可写入, 缺失字段没有空站位符

# 高级用法:使用 DictWriter 写入 CSV,提供了字段名的映射。
# 语法:csv.DicWriter(f, fieldnames=fields)
# 写入时可使用writeheader()写入标题,然后使用writerow(字典格式数据行)或writerows(多行数据)
with open('example1.csv', 'w', newline='') as file:
    fields = ['Name', 'Age', 'City']
    writer = csv.DictWriter(file, fieldnames=fields)  # 设置表头
    writer.writeheader()    # 写入表头
    
    # 按表头 写入数据
    writer.writerow({'Name': 'Alice', 'Age': 30, 'City': 'New York'})
    writer.writerow({'Name': 'Bob', 'Age': 25, 'City': 'Los Angeles'})
    writer.writerow({'Name': 'Bob', 'City': 'Los Angeles'})             # 数据字段 缺失 可以正确写入,缺失字段有空占位符
    # writer.writerow({'Name': 'Bob', 'Age': 25, 'City': 'Los Angeles', "class": 3})  # 数据多出字段不能写入,将抛出异常错误

Tips:

  • 读取 CSV 文件

语法:csv.reader(f, delimiter=',')

reader为生成器,每次读取一行,每行数据为列表格式,可以通过delimiter参数指定分隔符

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 基本用法
import csv

# 读取 CSV 文件
# 语法:csv.reader(f, delimiter=',')
# reader为生成器,每次读取一行,每行数据为列表格式,可以通过delimiter参数指定分隔符
with open('example.csv', 'r') as file:
    reader = csv.reader(file)
    for row in reader:
        print(row)

# 高级用法:使用 DictReader 读取 CSV,每行数据被映射到一个字典。
# 语法:csv.DicReader(f[, delimiter=','])
# 直接将标题和每一列数据组装成有序字典(OrderedDict)格式,无须再单独读取标题行
with open('example1.csv', 'r') as file:
    reader = csv.DictReader(file)
    for row in reader:
        print(row)

Tips:

  • 读写文件时,确保使用 newline=’’ 参数来防止在不同平台上的换行符问题。
  • 对于包含特殊字符的字段,如逗号 , 或引号 "/',csv 模块可以正确处理它们。
  • 在使用 DictReader 时,数据 字段 缺失 可以正确写入,缺失字段有空占位符。
  • 在使用 DictWriter 时,读取多余字段统一放到 key为 “None” 的 的列表中

2.3 Python处理CSV文件的高效技巧之Pandas库

  1. Pandas库简介 及 应用场景

Pandas库 是Python的一个开源数据分析处理库,它提供了高性能易用的数据结构和数据分析工具,用于进行数据的读取、清洗、过滤、聚合、视觉化等操作。

Pandas库主要有两种自己的数据结构,Series(一维数组)DataFrame(二维数组)

  • Series是一种类似于一维数组的对象,是由一组数据和一组与之相关的数据标签组成。
  • DataFrame是Pandas中的二维表格型数据结构,可以看作是由Series组成的字典。

Pandas库在Python中被广泛应用于数据预处理,包括数据清洗、数据转换和数据分析。下面是它的一些具体应用场景:

  • 数据导入导出:Pandas支持多种数据格式的导入导出,如csv,excel,sql等。
  • 数据预处理:可以进行数据清洗,填充缺失值,删除重复值,数据纠错等操作。
  • 数据分析:Pandas库能有效地分析数据,可以进行数据排序,数据统计等操作,还可以快速聚合、分组、合并、拼接数据。
  • 数据可视化:虽然Pandas主要用于数据的预处理,但它也可以进行简单的数据可视化。
  • 大规模数据处理:Pandas支持对大规模数据进行高效处理。
  • 时间序列分析:Pandas能够方便地进行日期范围生成,频率转换,移动窗口统计等时间序列相关的操作。

一些具体的应用领域包括金融、经济、社会科学、工程等涉及到大量数据处理和分析的领域。

  1. Pandas库部分方法及使用

第一步:pip 安装 Pandas库

1
pip install pandas

第二步:import 导入 Pandas库

1
import pandas as pd

第三部:Python 代码中使用 Pandas库,Pandas库中有许多方法能对数据进行处理和分析,下面列举一部分:

方法 功能描述
pd.read_csv() 用于读取csv文件并返回一个DataFrame
pd.read_excel() 用于读取Excel文件并返回一个DataFrame
DF.head() 返回前n行
DF.tail() 返回最后n行
DF.shape 返回行数和列数
DF.info() 返回DataFrame的摘要,包括索引类型、列类型、非空值数量等
DF.describe() 返回数据框的描述性统计信息,如均值、方差、最小值、最大值等
DF.sort_values() 返回按指定列值排序后的数据框,df.sort_values(by=‘Column_Name’)
DF.groupby() 用于执行分组操作,df.groupby(‘Column_Name’).mean()
DF.merge() 用于数据框的合并,merged_df = df1.merge(df2, on=‘Common_Column_Name’)
DF.join() 用于数据框的连接,df1.join(df2, on=‘Common_Column_Name’)
DF.concat() 用于数据框的串联,pd.concat([df1, df2])
DF.drop() 用于删除指定的行或列,df.drop(columns=‘Column_Name’)
DF.fillna() 填充缺失值,df.fillna(value=0)
Series.value_counts() 返回Series中每个值的频数,df[‘Column_Name’].value_counts()
DF.isnull() 判断是否有缺失值
DF.apply() 对DataFrame中的数据执行函数操作,df[‘Column_Name’].apply(lambda x: x**2)
DF.pivot_table() 创建数据透视表,pivot = df.pivot_table(index=‘Column1’, columns=‘Column2’,values=‘Column3’)
DF.plot() 创建各种静态、动态、交互式图表,df[‘Column_Name’].plot()

Tips: 上表中,pd 表示 pandas, DF 表示 DataFrame 对象,“Column_Name"代表你要操作的具体列名,“Column1”,“Column2”,“Column3” 代表相应的列名,“Common_Column_Name"代表两个DataFrame的公共列名。

以上这些只是Pandas库大量方法中的一部分,实际上Pandas还附带许多其他有用的功能和方法,能够满足各种数据处理和分析的需求。

  1. Pandas库处理 CSV 数据

基础操作:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# -*- coding: utf-8 -*-

import pandas as pd

# 1. 读写 cvs 文件
data = pd.read_csv('data.csv') # 这一行代码把CSV里的所有数据读取到一个 DataFrame(Pandas对象)中。DataFrame,就是数据工作台。
data.to_csv('processed_data.csv', index=False)

# 2. 快速浏览 数据收尾五行
print(data.head())  # 前五行
print(data.tail())  # 后五行

# 3. 修改列名操作
data.rename(columns={'old_name': 'new_name'}, inplace=True)

# 4. 精准筛选: 条件选择
filtered_data = data[data['age'] > 18]
subset = data[(data['age'] > 18) & (data['age'] < 30)]

# 5. 统计分析:计算平均值
average_age = data['age'].mean()

# 6. 拆分数据
data[['first_name', 'last_name']] = data['name'].str.split(' ', expand=True)

# 7. 合并数据
combined_data = pd.concat([data1, data2], ignore_index=True) # 合并两份数据

merged_data = pd.merge(data1, data2, on='common_key')   # 基于某个键合并

# 9. 数据清洗:去除空值
clean_data = data.dropna()  # 删除空值行
# 或者
data.fillna(value='default', inplace=True)  # 用默认值填充

# 10. 排序操作
sorted_data = data.sort_values(by='age', ascending=True)

高级技巧:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# -*- coding: utf-8 -*-

import pandas as pd

# 1. 高效过滤:有时,处理数据时需要基于复杂的逻辑筛选数据。利用query()函数可以提供接近自然语言的查询方式进行筛选。
complex_filtered = data.query('age > 18 and city == "New York"')

# 2. 处理日期时间:CSV中常有日期时间数据,pd.to_datetime() 可以将字符串形式的日期时间转换文Unix时间戳格式的时间
data['date'] = pd.to_datetime(data['date'])

# 3. 透视表(pivot table)快速汇总数据
pivot_table = data.pivot_table(index='city', values='age', aggfunc='mean') # 每个城市人们的平均年龄

# 4. 数据类型转换,改变列的数据类型,比如将字符串转为整型
data['age'] = data['age'].astype(int)

# 5. 高级合并:除了基本的合并,pd.DataFrame.join()提供了更多灵活性,特别是在处理具有相同索引的DataFrame时。
left.join(right, how='inner')  # 内连接

# 6. 数据预览:图形化理解
import matplotlib.pyplot as plt

data['age'].hist()  # 创建一个简单的 年龄分布 直方图。
plt.show()  
Licensed under CC BY-NC-SA 4.0
最后更新于 2023-07-14 21:58 CST