我正在尝试使用带有多处理模块的工作人员池从文本文件创建一系列NumPy数组。
def process_line(line, x,y,z,t):
sl = line.split()
x = np.append(x,float(sl[0].replace(',','')))
y = np.append(y,float(sl[1].replace(',','')))
z = np.append(z,float(sl[2].replace(',','')))
t = np.append(t,float(sl[3].replace(',','')))
def txt_to_HDF_converter(name, path_file):
#init objects
x = np.empty(0)
y = np.empty(0)
z = np.empty(0)
t = np.empty(0)
pool = mp.Pool(4)
jobs = []
with open(path_file) as f:
for line in f:
jobs.append(pool.apply_async(process_line,(line,x,y,z,t)))
#wait for all jobs to finish
for job in jobs:
job.get()
#clean up
pool.close()
[当在process_line
函数中分配数组时出现问题,就好像参数通过值传递一样,在循环结束时,我最终得到只有一个元素的数组。关于如何解决这个问题的任何想法?
您在此处的代码中将值作为元组的一部分传递:
jobs.append(pool.apply_async(process_line,(line,x,y,z,t)))
然后您在函数中隐式解压缩该元组:
def process_line(line, x,y,z,t):
然后您不更改现有值,而是使用以下几行来创建新值:
x = np.append(x,float(sl[0].replace(',','')))
y = np.append(y,float(sl[1].replace(',','')))
z = np.append(z,float(sl[2].replace(',','')))
t = np.append(t,float(sl[3].replace(',','')))
让我重复一遍:您不会更改原始数组(就像您期望的那样)。相反,您只是使用旧值来create新值,然后将它们分配给局部变量x
,y
,z
和t
。然后,您离开该函数,而忽略了新值。我会说这在函数之外永远不会有任何影响(也不会影响最后一个值)。
您有几种解决方法。
使用全局变量。这是一个快速解决方案,但风格不好,从长远来看,您会讨厌我的建议。但是,如果您只需要它快速运行,则可以选择此选项。
返回您的值。创建新值后,以某种方式返回它们,并确保下一次调用再次获得先前返回的值作为输入。这是功能方法。
通过引用传递您的值。您可以通过传递x
创建一个单元素列表来完成此操作。请参阅以下代码,了解如何执行此操作。传递引用是典型的C风格编程,但不是Python风格的(但可以)。许多IDE会警告您这样做的方式,而典型的Python开发人员将很难理解您在这里所做的事情。一个更好的选择是不使用简单列表,而是将数据放入某种对象中,该对象将通过引用传递。
x_ref = [x]
y_ref = [y]
y_ref = [y]
t_ref = [t]
with open(path_file) as f:
for line in f:
jobs.append(pool.apply_async(process_line,(line,x_ref,y_ref,z_ref,t_ref)))
然后需要调整process_line
以也期望引用:
def process_line(line, x_ref,y_ref,z_ref,t_ref):
sl = line.split()
x_ref[0] = np.append(x_ref[0],float(sl[0].replace(',','')))
y_ref[0] = np.append(y_ref[0],float(sl[1].replace(',','')))
z_ref[0] = np.append(z_ref[0],float(sl[2].replace(',','')))
t_ref[0] = np.append(t_ref[0],float(sl[3].replace(',','')))