如何在Linux上并行化Python程序

如何在Linux上并行化Python程序,python,linux,python-3.x,python-2.7,parallel-processing,Python,Linux,Python 3.x,Python 2.7,Parallel Processing,我有一个脚本,它接收输入一个文件名列表,并循环它们以生成每个输入文件的输出文件,因此我认为这是一个可以轻松并行化的情况 我有一台8芯的机器 我尝试在此命令上使用-parallel标志: python perfile_code.py list_of_files.txt 但我不能让它工作,具体的问题是:如何在Linux中用python命令在bash中使用parallel,以及上面提到的特定情况的参数 有一个Linux并行命令(sudo-apt-get-install-parallel),我在某处读

我有一个脚本,它接收
输入一个文件名列表
,并循环它们以生成每个输入文件的输出文件,因此我认为这是一个可以轻松并行化的情况

我有一台8芯的机器

我尝试在此命令上使用
-parallel
标志:

python perfile_code.py list_of_files.txt
但我不能让它工作,具体的问题是:如何在Linux中用python命令在bash中使用parallel,以及上面提到的特定情况的参数

有一个Linux并行命令(
sudo-apt-get-install-parallel
),我在某处读到它可以完成这项工作,但我不知道如何使用它

大多数互联网资源都解释了如何在bash中实现这一点,但它可以在bash中实现吗

请帮忙,谢谢

Based on an answer, here is a working example that is still not working, please suggest how to make it work.
我有一个包含2个文件的文件夹,我只想在本例中用不同的名称并行创建它们的副本

# filelist is the directory containing two file names, a.txt and b.txt.
# a.txt is the first file, b.xt is the second file
# i pass an .txt file with both the names to the main program

from concurrent.futures import ProcessPoolExecutor, as_completed
from pathlib import Path
import sys

def translate(filename):
    print(filename)
    f = open(filename, "r")
    g = open(filename + ".x", , "w")
    for line in f:
        g.write(line)

def main(path_to_file_with_list):
    futures = []
    with ProcessPoolExecutor(max_workers=8) as executor:
        for filename in Path(path_to_file_with_list).open():
            executor.submit(translate, "filelist/" + filename)
        for future in as_completed(futures):
            future.result()

if __name__ == "__main__":
     main(sys.argv[1])
根据你的评论,


@ Orbulu不,不考虑这个OpenSerux.com/Tune/18/5/GNU-并行,我想运行一个Python程序和这个并行。对于一个非常具体的情况…如果一个任意的转换程序可以被管道并行…为什么Python程序?

我认为这可能有帮助:

convert
不是任意选择的。之所以选择它,是因为它是一个更知名的程序,它(大致)将通过命令行提供的单个输入文件映射到也通过命令行提供的单个输出文件

典型的shell
for
循环可用于迭代列表。在您链接的文章中,它们显示了一个示例

for i in *jpeg; do convert $i $i.png ; done
这(同样粗略地)获取一个文件名列表,并将它们逐个应用于命令模板,然后运行该命令

这里的问题是的
必须等到一个命令完成后才能运行下一个命令,因此可能没有充分利用当今的多核处理器

parallel
是对
的一种替代。它假设一个命令可以同时执行多次,每次都有不同的参数,而每个实例都不会相互干扰

在本文中,它们使用
parallel

find . -name "*jpeg" | parallel -I% --max-args 1 convert % %.png
这相当于先前的
for
命令。区别(仍然大致)在于
parallel
同时运行模板化命令的多个变体,而不必等待每个变体完成


针对您的具体情况,为了能够使用并行
,您需要:

  • 调整python脚本,使其通过命令行接受一个输入(如文件名)和一个输出(也可能是文件名)
  • 了解如何设置
    parallel
    ,以便它可以接收这些文件名的列表,以便插入到命令模板中,从而在每个文件上分别运行python脚本

您只需使用普通shell
for
命令,并将
&
背景指示符附加到
for
命令中的python命令:

for file in `cat list_of_files.txt`;
   do python perfile_code.py $file &
done
当然,假设python代码将自己生成单独的输出

就这么简单。 虽然不常见,但一般来说,如果可以编辑程序,人们会喜欢使用Python本身来控制循环的并行执行。一个很好的方法是在Python中使用
concurrent.futures
创建一个包含8个工作线程的工作线程池——上面的shell方法将同时并行启动所有实例

假设您的代码有一个接受文件名的
translate
函数,那么您的Python代码可以写成:

from concurrent.futures import ProcessPoolExecutor, as_completed
from pathlib import Path:

def translate(filename):
    ...

def main(path_to_file_with_list):
    futures = []
    with ProcessPoolExecutor(max_workers=8) as executor:
        for filename in Path(path_to_file_with_list).open():
            executor.submit(translate, filename)
        for future in as_completed(futures):
            future.result()

if __name__ == "__main__":
     import sys
     main(argv[1])

这将不依赖于特殊的shell语法,并负责处理角落案例、数字或工人处理,这在bash中可能很难正确完成。

您的问题不清楚如何以串行方式运行任务。但如果我们假设你在跑步:

python perfile_code.py file1
python perfile_code.py file2
python perfile_code.py file3
:
python perfile_code.py fileN
然后,将其并行化的简单方法是:

parallel python perfile_code.py ::: file*
如果您有一个文件列表,每个文件一行,则使用:

parallel python perfile_code.py :::: filelist.txt

它将为每个cpu线程并行运行一个作业。因此,如果
filelist.txt
包含1000000个名称,那么它不会同时运行所有名称,而只会在一个作业完成时启动一个新作业。

为什么投票支持关闭?这是一个非常具体的问题,询问如何在bash中与python一起使用parallel,以及参数。我对问题进行了编辑,以使其更加清晰,请重新考虑。您显示出对并行主题的基本知识缺乏
-parallel
不是Python的有效命令行选项。并行操作的编程通常需要程序员采取主动的开发策略。我建议用谷歌搜索“python parallel”。@Ourobrus no,不考虑这一点,我想运行一个Python程序连同这个并行。对于一个非常具体的情况…如果一个任意的转换程序可以被管道化为并行的…为什么Python程序?这仍然需要你理解如何在一般情况下工作,并且你的软件能够在那个环境中运行。正如您所描述的,您当前的python脚本将不会受益于gnu
parallel
。阅读和理解你链接的文章将大大有助于你理解你需要做什么。没有“交钥匙”
——parallel
标志。您需要自己编写并行性,请参见:感谢提供一个有效的示例!我试过你的例子,请看一下编辑过的问题,它仍然不起作用。你写的例子在Python3和Python2中都起作用吗?Python3.5+中唯一的部分是
pathlib.Path
。在Python2.7中,只需使用普通的old
open(path\u to\u file\u wiith\u list)
,而无需从pathlib导入path
concurrent.futures
在Python2.7和更新版本中的工作原理相同。这可能会导致机器过载。如果
文件列表.txt
包含1