Python 如何从多处理中使用的函数中获取多个返回对象?

Python 如何从多处理中使用的函数中获取多个返回对象?,python,return,multiprocessing,pickle,Python,Return,Multiprocessing,Pickle,这可能是一个非常简单的问题,但肯定让我筋疲力尽。 为了使用多处理,我编写了以下代码。main函数创建两个进程,它们都使用相同的函数,称为prepare_input_data,但处理不同的输入数据集。此函数必须为每个输入返回多个对象和值,以便在此处不包括的代码的后续步骤中使用 我想要的是从我在多处理中使用的函数返回多个值或对象 def prepare_input_data(inputdata_address,temporary_address, output): p=current_pro

这可能是一个非常简单的问题,但肯定让我筋疲力尽。 为了使用多处理,我编写了以下代码。main函数创建两个进程,它们都使用相同的函数,称为prepare_input_data,但处理不同的输入数据集。此函数必须为每个输入返回多个对象和值,以便在此处不包括的代码的后续步骤中使用

我想要的是从我在多处理中使用的函数返回多个值或对象

def prepare_input_data(inputdata_address,temporary_address, output):
    p=current_process()
    name = p.name
    data_address = inputdata_address 
    layer = loading_layer(data_address)    

    preprocessing_object = Preprocessing(layer)
    nodes= preprocessing_object.node_extraction(layer)
    tree = preprocessing_object.index_nodes()
    roundabouts_dict , roundabouts_tree= find_roundabouts(layer.address, layer, temporary_address)

    #return layer, nodes, tree, roundabouts_dict, roundabouts_tree
    #return [layer, nodes, tree, roundabouts_dict, roundabouts_tree]
    output.put( [layer, nodes, tree, roundabouts_dict, roundabouts_tree])


if __name__ == '__main__':
    print "the data preparation in multi processes starts here"
    output=Queue() 
    start_time=time.time()
    processes =[]
    #outputs=[]
    ref_process = Process(name ="reference", target=prepare_input_data, args=("D:/Ehsan/Skane/Input/Skane_data/Under_processing/identicals/clipped/test/NVDB_test3.shp", "D:/Ehsan/Skane/Input/Skane_data/Under_processing/temporary/",output)) 
    cor_process = Process(name ="corresponding", target=prepare_input_data, args=("D:/Ehsan/Skane/Input/Skane_data/Under_processing/identicals/clipped/test/OSM_test3.shp", "D:/Ehsan/Skane/Input/Skane_data/Under_processing/temporary/",output))
    #outputs.append(ref_process.start)
    #outputs.append(cor_process.start)
    ref_process.start
    cor_process.start
    processes.append(ref_process)
    processes.append(cor_process)
    for p in processes:
        p.join()

    print "the whole data preparation took ",time.time()-start_time
    results={}
    for p in processes:
        results[p.name]=output.get()
    ########################
    #ref_info = outputs[0]
    # ref_nodes=ref_info[0]
先前错误 当我使用return时,ref_info[0]没有类型

错误: 根据答案,我将其更改为传递给函数的Queueu对象,然后使用put添加结果并获取它们以供进一步处理

Traceback (most recent call last):
File "C:\Python27\ArcGISx6410.2\Lib\multiprocessing\queues.py", line 262, in _feed
    send(obj)
UnpickleableError: Cannot pickle <type 'geoprocessing spatial reference object'> objects

您能否帮助我解决如何在多处理中从函数返回多个值的问题?

如果您希望从多处理中获取多个返回值,那么您可以这样做。下面是一个简单的示例,首先是串行python,然后是多处理:

因此,要从具有多处理的函数返回的值中获取多个值,您只需要有一个返回多个值的函数……您只需将值作为元组列表返回即可

从错误中可以看出,多处理的主要问题是大多数函数没有序列化。所以,如果你真的想做你看起来想做的事…我强烈建议你使用下面讨论的悲情。多处理的最大障碍是作为目标传递的函数必须是可序列化的。您可以对prepare_input_data函数进行一些修改……第一个修改是确保它是封装的。如果您的函数没有完全封装,例如,它在自己的范围之外有名称引用查找,那么它可能不会使用pickle进行pickle。这意味着,您需要在目标函数中包含所有导入,并通过函数输入传入任何其他变量。您看到的UnPicklableError错误是由于您的目标函数及其依赖项无法序列化造成的,而不是因为您无法从多处理返回多个值

Traceback (most recent call last):
File "C:\Python27\ArcGISx6410.2\Lib\multiprocessing\queues.py", line 262, in _feed
    send(obj)
UnpickleableError: Cannot pickle <type 'geoprocessing spatial reference object'> objects
尽管作为一种良好的实践,我还是要封装目标函数,但它可能有点乏味,并且可能会使代码慢下来一点。我还建议您将代码转换为使用dill和paths.multiprocessing-dill是一种高级序列化程序,可以pickle几乎所有python对象,paths提供了一个使用dill的多处理分支。这样,您就可以在管道中传递大多数python对象,即从池对象中传递可用的apply或map,而不必担心过于费力地重构代码以确保普通的pickle和多处理可以处理它

此外,我将使用异步映射,而不是执行上面的操作。paths.multiprocessing能够在map函数中获取多个参数,因此不需要像上面那样将它们包装在元组参数中。使用异步映射,接口应该更干净,如果需要,可以返回多个参数……只需将它们打包到一个元组中即可

这里有一些例子可以说明我上面提到的内容

返回多个值:

>>> from pathos.multiprocessing import ProcessingPool as Pool
>>> def addsub(x,y):
...   return x+y, x-y
... 
>>> a,b = range(10),range(-10,10,2)
>>> res = Pool().imap(addsub, a, b)
>>> 
>>> for i,ai in enumerate(a):
...   add,sub = res.next()
...   print("{a} + {b} = {p}; {a} - {b} = {m}".format(a=ai,b=b[i],p=add,m=sub))
... 
0 + -10 = -10; 0 - -10 = 10
1 + -8 = -7; 1 - -8 = 9
2 + -6 = -4; 2 - -6 = 8
3 + -4 = -1; 3 - -4 = 7
4 + -2 = 2; 4 - -2 = 6
5 + 0 = 5; 5 - 0 = 5
6 + 2 = 8; 6 - 2 = 4
7 + 4 = 11; 7 - 4 = 3
8 + 6 = 14; 8 - 6 = 2
9 + 8 = 17; 9 - 8 = 1
>>> 
异步映射:

悲情:

悲情:

我们仍然无法运行您的代码…但是如果您发布可以运行的代码,那么使用pathos fork和异步映射或其他方式来编辑您的代码可能会更有帮助


仅供参考:pathos的发行版有点过期了,也就是说太晚了,所以如果你想尝试,最好在这里获取代码:

共享状态并行编程是一条崎岖的道路,即使是有经验的程序员也会犯错。一种更适合初学者的方法是复制数据。这是在子流程之间移动数据的唯一方法,虽然不完全正确,但这是一个高级主题

例如,您需要设置一个multiprocessing.Queue来填充每个子流程的返回数据。之后,您可以将要读取的队列传递到下一阶段

对于多个不同的数据集,例如层、节点、树等,可以使用多个队列来区分每个返回值。为每个人使用一个队列似乎有点混乱,但它简单易懂且安全


希望对您有所帮助。

如果您使用jpe_类型。paralel的进程,它将返回进程目标函数的返回值,如下所示

import jpe_types.paralel


def fun():
    return 4, 23.4, "hi", None

if __name__ == "__main__":
    
    p = jpe_types.paralel.Process(target = fun)
    p.start()
    print(p.join())
否则你可以

import multiprocessing as mp

def fun(returner):
    returner.send((1, 23,"hi", None))

if __name__ == "__main__":
    processes = []
    for i in range(2):
        sender, recever = mp.Pipe()
        p = mp.Process(target = fun, args=(sender,))
        p.start()
        processes.append((p, recever))

    resses = []

    for p, rcver in processes:
        p.join()
        resses.append(rcver.recv())
    print(resses)

使用此连接将保证重新启动不会被scrambeld删除

您似乎忘记了实际提问@马库斯穆勒:现在可能更清楚了。。。。作为函数的返回。。。但是您目前没有返回任何内容,也没有查看从任何地方返回的值。你能写一封信吗
nimal和自包含的示例,显示您实际想要做什么?您发布的大多数代码似乎与多处理问题无关。@无用:我的函数中有带有语法return的返回值,但后来我将其改为Queue.put,因为我一直得到Nonetype。这个问题肯定一点也不清楚……但看看您的错误,似乎您将一个无法在python中进行pickle序列化的对象传递给了多处理队列。您可以传递一个可拾取的值字符串,例如整数,或者…*讨厌的解决方案*在全局变量中设置它。OP显然是一个初学者,没有掌握有关控制并发性和多处理组件的基本概念。在这种情况下,我不认为建议使用两个第三方软件包特别有帮助。从教育学角度更好地解释如何从概念上解决这一基本问题;然后提出实际实现的标准库方法。我大体上同意你的看法。然而上述软件包与我建议的软件包具有相同的接口,或者说是非常接近(如果不是完全的话)……我在b/c部分中建议了这些软件包,我是作者,部分原因是它们比python标准库软件包更干净,在概念上更易于初学者使用。这并没有解决如何返回多个价值观这是OP要求的。每个值都是一个队列。如果没有返回多个值,那么我不理解这个问题。我将编辑我的答案以澄清这一点。