并行Python:将另一个模块中编写的函数传递给'submit
我正在使用Parallel Python模块(pp
),想要把一个任务提交给一个工作者。但是,我想执行的函数在另一个模块里(是用Cython写的),我不知道怎么把这个函数名导入到新的工作者中。这里建议的方法是在函数内部导入模块"walkerc",但这行不通,因为walk本身是在walkerc中定义的,文件名是"walkerc.so"。
import pp
from walkerc import walk
# Other stuff here
ser = pp.Server()
# Some more definitions
ser.submit(walk, (it, params))
ser.submit(walk, (1000, params), modules = ("walkerc",), globals = globals())
上面的两个语句都失败了,我得到了以下错误信息:
追踪(最近的调用在最后):
文件 "", 第 1 行, 在 ser.submit(walk, (1000, params), modules = ("walkerc",), globals = globals())
文件 "/usr/lib/python2.7/site-packages/pp.py", 第 458 行, 在 submit sfunc = self.__dumpsfunc((func, ) + depfuncs, modules)
文件 "/usr/lib/python2.7/site-packages/pp.py", 第 629 行, 在 __dumpsfunc sources = [self.__get_source(func) for func in funcs]
文件 "/usr/lib/python2.7/site-packages/pp.py", 第 696 行, 在 __get_source sourcelines = inspect.getsourcelines(func)[0]
文件 "/usr/lib/python2.7/inspect.py", 第 690 行, 在 getsourcelines lines, lnum = findsource(object)
文件 "/usr/lib/python2.7/inspect.py", 第 526 行, 在 findsource file = getfile(object)
文件 "/usr/lib/python2.7/inspect.py", 第 420 行, 在 getfile 'function, traceback, frame, or code object'.format(object))
类型错误: '<'内置函数 walk'>' 不是模块、类、方法、函数、追踪、帧或代码对象
函数'walk'在主程序中导入得很好,但提交给新工作者的过程出现了问题。
我该如何正确指定函数名'walk'?我不想在调用它的同一个文件中定义'walk',因为我在Cython中修改过它,想要获得更好的性能。有没有其他的办法?
1 个回答
试着把你的 walk
函数改个名字,比如叫 mywalk
。因为错误信息提示,你的环境里似乎有一个内置的函数也叫 walk
,所以 inspect
模块就搞混了。
在我的系统上,我可以顺利地使用我导入的 walk
函数,没冲突,也不需要其他操作,函数会根据给定的参数执行:
import pp
from walkerc import walk
pps = pp.Server()
pps.submit(walk, args=(1,))
但是如果我传入 dir
,这个是肯定的内置函数:
pps.submit(dir)
我遇到的错误和你的一模一样:
Traceback (most recent call last): File "parallel.py", line 9, in pps.submit(dir) ... File ".../lib/python2.7/inspect.py", line 420, in getfile 'function, traceback, frame, or code object'.format(object)) TypeError: is not a module, class, method, function, traceback, frame, or code object
在下面讨论后的更新:
所以这里的问题是,Python把来自 C扩展 的成员当作内置函数来处理。上面的代码在普通的Python模块中可以正常工作,但当我从C扩展导入并传递函数时,我能重现原问题的错误。
因此,我把C扩展的函数调用包裹在一个普通的Python函数里,这样就解决了问题。注意,现在 walk
函数的导入被移动到了这个包裹函数里,这样它可以在调用时构建自己的上下文。
import pp
def walk(n):
import walkerc
return walkerc.walk(n)
def print_callback(result):
print('callback: ', result)
pps = pp.Server()
job = pps.submit(walk, args=(1,), callback=print_callback)