Python 更新进程之间的数据帧

Python 更新进程之间的数据帧,python,pandas,multiprocessing,Python,Pandas,Multiprocessing,我有一个(有点)最小的多处理测试示例,其中预期的输出是共享数据帧。但是,共享数据帧永远不会更新。在我的示例中,首先为测试目的创建10个文本文件,每个文本文件包含一个与文件名对应的整数。worker函数被赋予10个文件路径中的每个路径和共享数据帧的名称空间,然后它分析每个文件并将“结果”输入到数据帧中的适当位置(出于测试目的,它是文件中给定的整数值和列表中称为“常量”的每个常量的总和) 关于在每个任务完成后更新数据框,以及让变量共享发挥作用,有什么想法吗?我犯了一个简单的错误吗?有几篇文章建议使用

我有一个(有点)最小的多处理测试示例,其中预期的输出是共享数据帧。但是,共享数据帧永远不会更新。在我的示例中,首先为测试目的创建10个文本文件,每个文本文件包含一个与文件名对应的整数。worker函数被赋予10个文件路径中的每个路径和共享数据帧的名称空间,然后它分析每个文件并将“结果”输入到数据帧中的适当位置(出于测试目的,它是文件中给定的整数值和列表中称为“常量”的每个常量的总和)

关于在每个任务完成后更新数据框,以及让变量共享发挥作用,有什么想法吗?我犯了一个简单的错误吗?有几篇文章建议使用这种共享数据帧的方法,但它们通常有一个简单的结构,而我的结构导致共享失败。例如,我试图遵循此处给出的方法:

***我编辑了标题以反映不再使用名称空间的解决方案。我接受了被接受的答案,并对其进行了修改(如下),以尽可能少地使用代码,并且不处理异常。如果需要多处理,可以导入ProcessPoolExecutor

from concurrent.futures import ThreadPoolExecutor, as_completed
import pandas as pd
import os

test_folder = r'C:\test_files'
test_filenames = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']
constants = [10, 15, 30, 60, 1440]

ct = 1

for filename in test_filenames:
    with open(test_folder + '\\' + filename + '.txt', 'w') as f:
        f.write(str(ct))

    ct += 1

def worker_function(file_path):

    with open(file_path) as f:
        value = int(f.readline())

    result_list = []
    filename = file_path.split( '\\' )[-1]    
    result_list.append(filename)
    for constant in constants:
        result = value + constant
        result_list.append(result)

    return result_list

if __name__ == '__main__':

    files = os.listdir(test_folder)
    file_paths = [test_folder + '\\' + file for file in files]
    output_df = pd.DataFrame(columns=constants, index=files)

    with ThreadPoolExecutor(max_workers=4) as executor:
        pool = {executor.submit(worker_function, p): p for p in file_paths}

        for future in as_completed(pool):
            worker_result = future.result()
            output_df.loc[worker_result[0]] = worker_result[1:]
该模块有助于工作流程中的CPU或I/O受限于令人尴尬的并行数据查找或处理步骤

对于您的情况,它应该如下所示。我不在Windows上,所以我没有尝试重新创建文件名来测试它,但我希望该结构能让您了解这种模式。请注意,我使用多线程而不是进程,因为辅助函数主要参与I/O而不是处理

from concurrent.futures import ThreadPoolExecutor, as_completed
import pandas as pd
import os

test_folder = r'C:\test_files'
test_filenames = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']
constants = [10, 15, 30, 60, 1440]

ct = 1

for filename in test_filenames:
    with open(test_folder + '\\' + filename + '.txt', 'w') as f:
        f.write(str(ct))

    ct += 1

def worker_function(file_path):

    with open(file_path) as f:
        value = int(f.readline())

    result_list = []
    filename = file_path.split( '\\' )[-1]    
    result_list.append(filename)
    for constant in constants:
        result = value + constant
        result_list.append(result)

    return result_list

if __name__ == '__main__':

    files = os.listdir(test_folder)
    file_paths = [test_folder + '\\' + file for file in files]
    output_df = pd.DataFrame(columns=constants, index=files)

    with ThreadPoolExecutor(max_workers=4) as executor:
        pool = {executor.submit(worker_function, p): p for p in file_paths}

        for future in as_completed(pool):
            worker_result = future.result()
            output_df.loc[worker_result[0]] = worker_result[1:]
从concurrent.futures导入ThreadPoolExecutor,完成时
导入操作系统
作为pd进口熊猫
test\u folder=r'C:\test\u files'
测试文件名=['1','2','3','4','5','6','7','8','9','10']
常数=[10,15,30,60,1440]
#ct=1
def文件_计数器(ct=1):
对于测试文件名中的文件名:
打开(test_folder+'\\'+filename+'.txt',w')作为f:
f、 写(str(ct))
#无需将f.close()与上下文管理器一起使用
ct+=1
def辅助功能(文件路径):
结果_列表=[]
打开(文件路径)为f时:
value=int(f.readline())
#无需将f.close()与上下文管理器一起使用
filename=file\u path.split('\\')[-1]
对于常数中的常数:
结果=值+常数
result_list.append((常量、文件名、结果))
返回结果列表
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
file_counter()#将执行保持在if…main以下
files=os.listdir(test\u文件夹)
文件路径=[test\u folder+'\\'+file for file in files]
数据帧_集合=[]
#对于I/O,您应该更喜欢线程而不是进程
使用ThreadPoolExecutor(最大工作线程数=4)作为执行器:
pool={executor.submit(worker_函数,p):p代表文件_路径中的p}
对于未来已完成的项目(池):
worker\u result=future.result()
如果isinstance(worker_结果,异常):#选择您自己的异常类型
#处理异常
通过
其他:
输出\ df=pd.DataFrame(数据=工作者\结果,列=文件,索引=常量)
dataframe_collection.append(输出_df)
#现在连接所有数据帧
单帧df=pd.concat(数据帧集合)

我进行了编辑,从worker函数内部的名称空间创建了“dataframe”变量。此更改导致某些dataframe列被正确填充,但其中一些列仍为空。每次运行代码时,重新运行代码会给出不同的填充列和不同的空白列。有时它们甚至都填写正确。进程是否相互干扰?“……在进行并发编程时,通常最好尽量避免使用共享状态。在使用多个进程时尤其如此。”]是否存在无法在父进程中收集结果然后追加到数据帧的原因?没有特别的原因。这是否需要让worker函数返回一个结果列表?然后我用worker函数之外的结果列表更新dataframe?我在概念化上遇到了困难,因为我不确定如何获得worker函数的输出,如果这是真的。谢谢,我正在考虑这个结构。同时,当我运行这个时,我得到了一个新的错误<代码>断言错误:通过了10列,通过的数据有3列参考第46行,我相信正如我提到的,我还没有测试。它应该是第26行,在那里我将要附加的数据构造为
(常量、文件名、结果)
。以前,您直接在已经实例化的数据帧中设置值。现在,您必须将一个可接受的结构传递到
DataFrame
构造函数中。您应该能够通过正确定义
worker\u函数的返回值来解决此问题,以适应数据帧。一旦您在数据帧中的正确位置获得结果,并且维度得到正确处理,它就会起作用。谢谢