生成器
原始代码
ans_file_paths = [path for path in file_paths if any(id_ in path for id_ in ids_set)]
修改后代码
def file_generator(root_dir, ids_set):
"""生成器:用于生成符合条件的文件路径"""
file_pattern = os.path.join(root_dir, '*csv')
file_paths = glob(file_pattern)
for path in file_paths:
if any(id_ in path for id_ in ids_set):
yield path
原始代码解释:
- 列表推导式:这段代码使用了 Python 中的列表推导式(list comprehension),是一种简洁的方式来生成一个列表。
- 条件筛选:它从
file_paths
列表中筛选出符合条件的文件路径。具体来说,它会检查ids_set
中的每个id_
是否出现在路径path
中。 - 结果:最终,
ans_file_paths
将包含所有符合条件的文件路径。
修改后解释:
-
定义了一个生成器函数:修改后的代码将原来的列表推导式转换成了一个生成器函数
file_generator
。生成器是一种特殊的迭代器,允许你逐个生成值,而不是一次性生成所有值。 -
使用
yield
关键字:在file_generator
函数中,使用了yield
关键字。当函数执行到yield
时,它会返回一个值并暂停执行,以后再调用时会从暂停的地方继续执行。这意味着生成器不会一次性将所有结果都计算出来,而是按需生成。 -
内存效率:使用生成器的一个主要好处是内存效率。原始代码会一次性创建一个包含所有符合条件路径的列表,这在处理大量文件路径时可能会消耗大量内存。而生成器则只会在需要时生成一个路径,这样可以节省内存。
-
可读性和可重用性:将代码封装在函数中提高了可读性和可重用性。你可以多次调用
file_generator
,并在不同的地方使用它,而不必每次都写一遍筛选逻辑。
总结
- 原始代码:使用列表推导式一次性生成所有符合条件的文件路径,可能会占用较多内存。
- 修改后代码:使用生成器按需生成文件路径,节省内存,提高了代码的可读性和可重用性。
案例1
原代码:
def main():
dir = r'F:\02-data\test'
file_paths = glob(os.path.join(dir, f'*.csv'))
for file_path in file_paths:
data = pd.read_csv(file_path, encoding='gbk')
out_name = re.split('[\\\\, .]', file_path)[-2]
data.to_csv(r'F:\02-data\test\无加密\{}.txt'.format(out_name), index=False, encoding='utf8')
print('ok')
修改后代码:
def file_generator(dir):
"""生成器,用于逐个读取CSV文件路径"""
file_paths = glob(os.path.join(dir, '*.csv'))
for file_path in file_paths:
yield file_path
def main():
dir = r'F:\02-data\test'
output_dir = r'F:\02-data\test\无加密'
# 使用生成器
for file_path in file_generator(dir):
data = pd.read_csv(file_path, encoding='gbk')
out_name = re.split('[\\\\, .]', file_path)[-2]
data.to_csv(os.path.join(output_dir, f'{out_name}.txt'), index=False, encoding='utf8')
增加并行计算:
import os
import re
import pandas as pd
from glob import glob
from concurrent.futures import ProcessPoolExecutor
def process_file(file_path):
"""处理单个文件的函数"""
data = pd.read_csv(file_path, encoding='gbk')
out_name = re.split('[\\\\, .]', file_path)[-2]
output_path = os.path.join(r'F:\02-data\test\无加密', f'{out_name}.txt')
data.to_csv(output_path, index=False, encoding='utf8')
def file_generator(dir):
"""生成器,用于逐个读取CSV文件路径"""
file_paths = glob(os.path.join(dir, '*.csv'))
for file_path in file_paths:
yield file_path
def main():
dir = r'F:\02-data\test'
num_workers = 4 # 指定进程数量,可以根据需要进行调整
# 使用ProcessPoolExecutor进行并行处理
with ProcessPoolExecutor(max_workers=num_workers) as executor:
executor.map(process_file, file_generator(dir)) # 直接使用生成器