在数据文件夹上同时运行4个Python脚本实例

6 投票
4 回答
1821 浏览
提问于 2025-04-17 10:52

我们有一个文件夹里有50个数据文件(下一代DNA序列),需要通过运行一个Python脚本来转换每一个文件。每个文件运行这个脚本需要5个小时,而且这个脚本是单线程的,主要消耗CPU资源(CPU核心的使用率达到99%,而磁盘的读写几乎没有)。

因为我有一台4核的电脑,所以我想同时运行4个这个脚本实例,这样可以大大加快处理速度。

我想我可以把数据分成4个文件夹,然后同时在每个文件夹上运行以下的bash脚本:

files=`ls -1 *`
for $file in $files;
do
   out = $file+=".out" 
   python fastq_groom.py $file $out
done

不过,应该有更好的方法在一个文件夹里运行这个脚本。我们可以使用Bash/Python/Perl/Windows来实现这个。
(可惜把这个脚本改成多线程的超出了我们的能力范围)


使用@phs的xargs解决方案是我们解决这个问题最简单的方法。不过我们还是希望原开发者能实现@Björn的建议。再次感谢!

4 个回答

1

试试这个:

#!/bin/bash

files=( * )
for((i=0;i<${#files[@]};i+=4)); do
  { 
     python fastq_groom.py "${files[$i]}" "${files[$i]}".out &
     python fastq_groom.py "${files[$i+1]}" "${files[$i+1]}".out &
     python fastq_groom.py "${files[$i+2]}" "${files[$i+2]}".out &
     python fastq_groom.py "${files[$i+3]}" "${files[$i+3]}".out &
  }
done

下面的代码会把所有文件放进一个叫做 files 的数组里。接着,它会在前四个文件上启动四个 Python 进程,并把它们放到后台运行。当这四个进程都完成后,它会继续处理接下来的四个文件。虽然这样做没有一直保持四个进程同时运行那么高效,但如果所有进程的运行时间差不多,这样的效果也差不多。

另外,拜托,千万不要那样使用 ls 的输出。直接用标准的通配符匹配就可以,比如 for files in *.txt; do ...; done

7

你可以使用 multiprocessing 这个模块。我想你可能有一堆文件需要处理,还有一个函数要对每个文件进行操作。那么你可以像这样简单地使用一个工作池:

from multiprocessing import Pool, cpu_count

pool = Pool(processes=cpu_count)
pool.map(process_function, file_list, chunksize=1)

如果你的 process_function 函数没有返回值,那你就可以直接忽略它的返回值。

1

看看这个 xargs 命令。它的 -P 选项可以让你设置并行处理的程度。简单来说,你可以通过这个选项来控制同时运行多少个任务。具体来说,像下面这样写应该能满足你的需求:

ls files* | awk '{print $1,$1".out"}' | xargs -P 4 -n 2 python fastq_groom.py

撰写回答