我使用Python的multiprocessing.Pool库以下面的方式创build多个进程:
def parallel_function(f): def easy_parallize(f, sequence): """ assumes f takes sequence as input, easy w/ Python's scope """ pool = Pool(processes=8) # depends on available cores result = pool.map(f, sequence) # for i in sequence: result[i] = f(i) cleaned = [x for x in result if x is not None] # getting results cleaned = np.asarray(cleaned) pool.close() pool.join() return cleaned return partial(easy_parallize, f)
其中f是执行工作的函数,sequence是参数,请参阅本教程的http://zqdevres.qiniucdn.com/data/20150702120338/index.html 。
使用PyInstaller 3.1.1将该项目打包到单个Windows EXE中。 与–onedir选项。 PyInstaller创buildEXE没有问题,我能够执行不使用multithreading的程序的部分没有问题。
当我尝试执行使用上述多处理function的程序部分时,出现了我的问题。 然后,程序将失败,并显示以下错误消息(由每个子线程覆盖):
File "multiprocessing\context.py", line 148, in freeze_support File "multiprocessing\spawn.py", line 74, in freeze_support File "multiprocessing\spawn.py", line 106, in spawn_main File "multiprocessing\spawn.py", line 115, in _main File "multiprocessing\spawn.py", line 221, in prepare File "multiprocessing\context.py", line 231, in set_start_method RuntimeError: context has already been set classifier_v3_gui returned -1
freeze_support来自https://github.com/pyinstaller/pyinstaller/wiki/Recipe-Multiprocessing的一个build议,其中main应该包含第一行的调用:
if name == "__main__": multiprocessing.freeze_support()
PyInstaller构build的Windows EXE在多处理失败时已经讨论了类似的问题,并且在上面的链接中提到了解决scheme,但是,a)讨论的–onedir解决scheme对于我来说似乎不起作用,正如您从错误信息我得到,b)我不知道_Popen是如何与Pool-ing相关的,所以对于–onefile,我甚至不知道如何实现类的重定义。
如果我在main中不使用multiprocessing.freeze_support(),那么程序的行为会不同,因为RuntimeError不会发生,相反,我得到了我的程序的使用说明一遍又一遍地打印到cmd,我假定每个产生的进程这些试图自己调用EXE,这显然不是应该发生的事情。
不用说,程序运行没有问题,作为一个.py脚本。
我正在使用32位Python 3.4(在Python 10中也有相同的multithreading问题)。
我能想到的唯一的其他解决scheme是重写我的解决scheme使用多处理.Process而不是multiprocessing.Pool,因为似乎有一个修复。 如果你有一个相当低的努力做我的池function正在做,我会解决这个问题。
你有没有找到解决你的问题? 我有同样的问题,但我设法使它与一个简单的代码工作。 然而,它不能用我的完整编码(使用sklearn)。 如果你设法使它工作,让我知道,它也可能帮助我。
这里是为我工作的编码:
import multiprocessing import time def func (param1, param2): print ("hello " + str (param1)) time.sleep (param2) print ("Hello again " + str (param1)) return "test " + str (param1) def main (): lParams = [("test1", 3), ("test2", 2), ("test3", 1)] args = [] for param1, param2 in lParams: tup = (param1, param2) args.append (tup) with multiprocessing.Pool (multiprocessing.cpu_count ()) as p: results = [p.apply_async (func, a) for a in args] for r in results: print ("Returned " + r.get ()) if __name__ == '__main__': multiprocessing.freeze_support() main ()
请注意,我在pyinstaller(一个目录)中使用“-D”选项来编译我的应用程序。