我有以下函数:
def copy_file(source_file, target_dir):
pass
现在我想使用multiprocessing
同时执行这个函数:
p = Pool(12)
p.map(lambda x: copy_file(x,target_dir), file_list)
问题是,lambda函数无法被 pickled,所以会失败。如何以最简洁(Pythonic)的方式解决这个问题?
我有以下函数:
def copy_file(source_file, target_dir):
pass
现在我想使用multiprocessing
同时执行这个函数:
p = Pool(12)
p.map(lambda x: copy_file(x,target_dir), file_list)
问题是,lambda函数无法被 pickled,所以会失败。如何以最简洁(Pythonic)的方式解决这个问题?
使用函数对象:
class Copier(object):
def __init__(self, tgtdir):
self.target_dir = tgtdir
def __call__(self, src):
copy_file(src, self.target_dir)
要运行你的 Pool.map
:
p.map(Copier(target_dir), file_list)
对于Python2.7+或Python3,您可以使用functools.partial:
import functools
copier = functools.partial(copy_file, target_dir=target_dir)
p.map(copier, file_list)
functools.partial
在 Python 2.7 中也可进行 pickle 序列化。 - pythonic metaphor问题有点旧了,但是如果你仍在使用Python 2,我的答案可能会有用。
关键是使用 pathos 项目的一部分:multiprocess,它是 multiprocessing 的分支版本。它摆脱了原始 multiprocess 的烦人限制。
安装:pip install multiprocess
用法:
>>> from multiprocess import Pool
>>> p = Pool(4)
>>> print p.map(lambda x: (lambda y:y**2)(x) + x, xrange(10))
[0, 2, 6, 12, 20, 30, 42, 56, 72, 90]
你可以使用starmap()
和池化来解决这个问题。
假设你有一个文件列表,比如在你的工作目录中,你想要将这些文件复制到一个位置,那么你可以import os
并使用os.system()
在Python中运行终端命令。这将使您轻松地移动文件。
但是,在开始之前,您需要创建一个变量res = [(file, target_dir) for file in file_list]
,它将存储每个文件与目标目录。
它看起来像...
[('test1.pdf', '/home/mcurie/files/pdfs/'), ('test2.pdf', '/home/mcurie/files/pdfs/'), ('test3.pdf', '/home/mcurie/files/pdfs/'), ('test4.pdf', '/home/mcurie/files/pdfs/')]
显然,对于这种用例,您可以通过将每个文件和目标目录存储在一个字符串中来简化此过程,但这将降低使用此方法的洞察力。
思路是starmap()
将接受res
的每个组件并将其放入函数copy_file(source_file, target_dir)
中并同步执行它们(这受限于您CPU的核心数量)。
因此,第一个操作线程将如下所示
copy_file('test1.pdf', '/home/mcurie/files/pdfs/')
希望这可以帮助您。完整代码如下。
from multiprocessing.pool import Pool
import os
file_list = ["test1.pdf", "test2.pdf", "test3.pdf", "test4.pdf"]
target_dir = "/home/mcurie/files/pdfs/"
def copy_file(source_file, target_dir):
os.system(f"cp {source_file} {target_dir + source_file}")
if __name__ == '__main__':
with Pool() as p:
res = [(file, target_dir) for file in file_list]
for results in p.starmap(copy_file, res):
pass
从this的答案中可以看出,pathos让你可以直接运行lambda表达式p.map(lambda x: copy_file(x,target_dir), file_list)
,省去了所有的解决方法/黑客工具。
copy_file
是一个方法中的self.copy_file
呢? - Константин Ван