Python 并行读取文件并参数化类参数
假设我有一个类,并且希望并行地从磁盘读取几个文件,并参数化类参数。最正确的方法是什么(以及如何做)Python 并行读取文件并参数化类参数,python,multithreading,python-asyncio,Python,Multithreading,Python Asyncio,假设我有一个类,并且希望并行地从磁盘读取几个文件,并参数化类参数。最正确的方法是什么(以及如何做) 主线程应该等待load_data()操作结束,然后再进行其他操作 我考虑过线程,因为它只是I/O操作 非并行实现示例(单线程): 在大多数情况下,I/O操作不受CPU的限制,因此使用多个进程是一种过度使用。使用多个线程可能很好,但是pb.read\u csv不仅可以读取文件,而且可以解析它,这是CPU限制的。我建议您在asyncio最初用于此目的时,立即使用它从磁盘读取文件。以下是执行此操作的
- 主线程应该等待load_data()操作结束,然后再进行其他操作
在大多数情况下,I/O操作不受CPU的限制,因此使用多个进程是一种过度使用。使用多个线程可能很好,但是pb.read\u csv不仅可以读取文件,而且可以解析它,这是CPU限制的。我建议您在asyncio最初用于此目的时,立即使用它从磁盘读取文件。以下是执行此操作的代码:
import asyncio
import aiofiles
async def read_file(file_name):
async with aiofiles.open(file_name, mode='rb') as f:
return await f.read()
def read_files_async(file_names: list) -> list:
loop = asyncio.get_event_loop()
return loop.run_until_complete(
asyncio.gather(*[read_file(file_name) for file_name in file_names]))
if __name__ == '__main__':
contents = read_files_async([f'files/file_{i}.csv' for i in range(10)])
print(contents)
函数read\u files\u async
返回文件内容列表(字节缓冲区),您可以将其传递到pd.read\u csv
我认为仅对文件读取进行优化应该足够了,但您可以使用多个进程并行解析文件内容(线程和异步不会提高解析进程的性能):
您应该根据您的机器规格设置
内核数
。使用Python3的可能解决方案
多亏了
with
子句,“主”线程在load_data()
完成之前不会继续运行?@eranmose实际上,以ThreadPoolExecutor()为执行者的正在使用executor.submit进行阻塞。提交(load_data_woker,self.a,'a.csv')
,self.a
(以及所有self.vars)都没有参数化。@moshe修复了,如果我们想从Workers获取处理过的数据,我们应该使用queue。您可以稍微修改put()方法来放置字典条目,即:data\u queue.put({'name':file\u name,'data':pd.read\u csv(file\u name)})
import asyncio
import aiofiles
async def read_file(file_name):
async with aiofiles.open(file_name, mode='rb') as f:
return await f.read()
def read_files_async(file_names: list) -> list:
loop = asyncio.get_event_loop()
return loop.run_until_complete(
asyncio.gather(*[read_file(file_name) for file_name in file_names]))
if __name__ == '__main__':
contents = read_files_async([f'files/file_{i}.csv' for i in range(10)])
print(contents)
import multiprocessing as mp
NUMBER_OF_CORES = 4
pool = mp.Pool(NUMBER_OF_CORES)
pool.map(pb.read_csv, contents)
from concurrent.futures import ThreadPoolExecutor
import queue
import pandas as pd
def load_data_worker(data_queue, file_name):
data_queue.put(pd.read_csv(file_name))
class DataManager(object):
def __init__(self):
self.data_queue = queue.Queue()
self.data_arr = []
def load_data(self):
with ThreadPoolExecutor() as executor:
executor.submit(load_data_woker, self.data_queue, 'a.csv')
executor.submit(load_data_woker, self.data_queue, 'b.csv')
# ...
executor.submit(load_data_woker, self.data_queue, 'f.csv')
# dumping Queue of loaded data to array
self.data_arr = list(self.data_queue.queue)
if __name__ == '__main__':
dm = DataManager()
dm.load_data()
# Main thread is waiting for load_data to finish.
print("finished loading data")