Skip to main content
 首页 » 编程设计

python之使用 Pool.map() 将函数作为参数传递给进程目标

2024年10月17日31Renyi-Fan

我正在开发一个软件来使用不同的方法(单线程、多线程、多进程)对一些 Python 脚本进行基准测试。所以我需要在不同的进程中执行相同的函数(使用相同的参数等)。

如何将要执行的函数作为参数传递给进程目标?

我目前的理解是,对函数的引用无法工作,因为引用的函数对其他进程不可见,这就是我尝试使用共享内存的自定义管理器的原因。

这里是一个简化的代码:

#!/bin/python 
 
from multiprocessing import Pool 
from multiprocessing.managers import BaseManager 
from itertools import repeat 
 
class FunctionManager(BaseManager): 
    pass 
 
def maFunction(a, b): 
    print(a + b) 
 
def threadedFunction(f_i_args): 
    (f, i, args) = f_i_args 
    f(*args) 
 
FunctionManager.register('Function', maFunction) 
 
myManager = FunctionManager() 
myManager.start() 
 
myManager.Function(0, 0) # Test 1 
threadedFunction((maFunction, 0, (1, 1))) # Test 2 
 
p = Pool() 
args = zip(repeat(myManager.Function), range(10), repeat(2, 2)) 
p.map(threadedFunction, args) # Does not work 
p.join() 
 
myManager.shutdown() 

“p.map()”的当前酸洗错误如下:

2 
0 
Traceback (most recent call last): 
  File "./test.py", line 27, in <module> 
    p.map(threadedFunction, args) # Does not work 
  File "/usr/lib/python3.5/multiprocessing/pool.py", line 260, in map 
    return self._map_async(func, iterable, mapstar, chunksize).get() 
  File "/usr/lib/python3.5/multiprocessing/pool.py", line 608, in get 
    raise self._value 
  File "/usr/lib/python3.5/multiprocessing/pool.py", line 385, in _handle_tasks 
    put(task) 
  File "/usr/lib/python3.5/multiprocessing/connection.py", line 206, in send 
    self._send_bytes(ForkingPickler.dumps(obj)) 
  File "/usr/lib/python3.5/multiprocessing/reduction.py", line 50, in dumps 
    cls(buf, protocol).dump(obj) 
_pickle.PicklingError: Can't pickle <class 'weakref'>: attribute lookup weakref on builtins failed 

请您参考如下方法:

我在运行您的代码时遇到了一些不同的错误。我认为你的关键问题是你将一个函数传递给 FunctionManager.register() 而不是一个类。我还必须删除您的 zip 才能使其正常工作并手动创建一个列表,但这您可能可以解决。这只是一个例子。

以下代码使用您的确切结构工作并执行某些操作。我会做一些不同的事情,而不是使用 BaseManager,但我假设你有你的理由。

#!/usr/bin/python3.5 
 
from multiprocessing import Pool 
from multiprocessing.managers import BaseManager 
from itertools import repeat 
 
class FunctionManager(BaseManager): 
    pass 
 
 
class maClass(object): 
    def __init__(self): 
        pass 
    def maFunction(self,a, b): 
        print(a + b) 
 
def threadedFunction(f_i_args): 
    (f, i, args) = f_i_args 
    f(*args) 
 
FunctionManager.register('Foobar', maClass) 
 
myManager = FunctionManager() 
myManager.start() 
foobar = myManager.Foobar() 
 
foobar.maFunction(0, 0) # Test 1 
threadedFunction((foobar.maFunction, 0, (1, 1))) # Test 2 
 
p = Pool() 
#args = list(zip(repeat(foobar.maFunction), range(10), repeat(2, 2))) 
args = [] 
for i in range(10): 
    args.append([foobar.maFunction, i, (i,2)]) 
 
 
p.map(threadedFunction, args) # Does now work 
p.close() 
p.join() 
 
myManager.shutdown() 

还是我完全误解了你的问题?

汉奴