序列化迭代器对象以在Python中的进程之间传递

时间:2015-10-30 21:04:19

标签: python matrix pickle multiprocess

我有一个python脚本,可以从列表中计算矩阵的特征值,我想将这些特征值以与原始矩阵相同的顺序插入到另一个集合中,我想通过生成多个进程来实现这一点。

这是我的代码:

import time
import collections
import numpy as NP
from scipy import linalg as LA

from joblib import Parallel, delayed

def computeEigenV(unit_of_work):
    current_index = unit_of_work[0]
    current_matrix = unit_of_work[1]

    e_vals, e_vecs = LA.eig(current_matrix)
    finished_unit = (current_index, lowEV[::-1])
    return finished_unit

def run(work_list):
    pool = Parallel( n_jobs = -1, verbose = 1, pre_dispatch = 'all')
    results = pool(delayed(computeEigenV)(unit_of_work) for unit_of_work in work_list)
return results

if __name__ == '__main__':
    # create original array of matrices
    original_matrix_list = []
    work_list = []

    #basic set up so we can run this test
    for i in range(0, 100):
        # generate the matrix & unit or work
        matrix = NP.random.random_integers(0, 100, (500, 500))
        #insert into respective resources
        original_matrix_list.append(matrix)

    for i, matrix in enumerate(original_matrix_list):
        unit_of_work = [i, matrix]
        work_list.append(unit_of_work)

    work_result = run(work_list)

所以work_result应该在所有过程完成后保存每个矩阵的所有特征值。我使用的迭代器是unit_of_work,它是一个包含矩阵索引(来自original_matrix_list)和矩阵本身的列表。

奇怪的是,如果我通过执行python matrix.py来运行此代码,一切都很完美。但是当我使用auto(一个为微分方程计算的程序?)来运行我的脚本时,输入auto matrix.py会给我以下错误:

Traceback (most recent call last):
  File "matrix.py", line 50, in <module>
    work_result = run(work_list)
  File "matrix.py", line 27, in run
    results = pool(delayed(computeEigenV)(unit_of_work) for unit_of_work in work_list)
  File "/Library/Python/2.7/site-packages/joblib/parallel.py", line 805, in __call__
    while self.dispatch_one_batch(iterator):
  File "/Library/Python/2.7/site-packages/joblib/parallel.py", line 658, in dispatch_one_batch
    tasks = BatchedCalls(itertools.islice(iterator, batch_size))
  File "/Library/Python/2.7/site-packages/joblib/parallel.py", line 69, in __init__
    self.items = list(iterator_slice)
  File "matrix.py", line 27, in <genexpr>
    results = pool(delayed(computeEigenV)(unit_of_work) for unit_of_work in work_list)
  File "/Library/Python/2.7/site-packages/joblib/parallel.py", line 162, in delayed
    pickle.dumps(function)
TypeError: expected string or Unicode object, NoneType found

注意:当我使用auto运行时,我必须将if __name__ == '__main__':更改为if __name__ == '__builtin__':

我查找了这个错误,似乎我没有正确地序列化迭代器unit_of_work,当它传递给不同的进程时。然后我尝试使用serialized_unit_of_work = pickle.dumps(unit_of_work),传递它,并在需要使用迭代器时执行pickle.loads,但我仍然得到相同的错误。

有人可以帮我指出正确的方向,我该如何解决这个问题?我在使用pickle.dump(obj, file[, protocol])时犹豫不决,因为最终我将运行它来计算数千个矩阵的特征值,如果可能的话,我真的不想创建那么多文件来存储序列化的迭代器。

谢谢! :)

1 个答案:

答案 0 :(得分:0)

你不能在python2.7中腌制迭代器(但你可以从3.4开始)。

此外,__main__中的酸洗工作方式与__main__中的工作方式不同,auto似乎与__main__做了一些奇怪的事情。当一个特定对象的pickle失败时,你经常会注意到的是,如果不是直接运行带有对象的脚本,而是运行一个脚本作为main,它将脚本的一部分导入为&#34;难以 - 序列&#34;对象,然后酸洗将成功。这是因为对象将在命名空间级别上通过引用进行pickle,其中&#34;难以&#34;对象生活......因此它永远不会被直接腌制。

所以,你可以通过添加参考层......文件导入或类来腌制你想要的东西。但是,如果你想腌制迭代器,除非你至少移动到python3.4,否则你运气不好。