需要在Ruffus管道中运行函数之前制作一组文件

时间:2010-03-17 21:11:21

标签: python cluster-computing distributed-computing pipeline ruffus

我正在使用ruffus来编写管道。我有一个多次并行调用的函数,它创建了几个文件。我想创建一个函数“combineFiles()”,在完成所有这些文件后调用它。由于它们在群集上并行运行,因此它们不会全部完成。我编写了一个函数'getFilenames()',它返回需要创建的文件名集,但是如何让combineFiles()等待它们在那里呢?

我尝试了以下内容:

@pipelineFunction
@files(getFilenames)
def combineFiles(filenames):
  # I should only be called if every file in the list 'filenames' exists

我也尝试过装饰者:

@merge(getFilenames)

但这也不起作用。在生成getFilenames给出的文件之前,combineFiles仍会被错误地调用。如何使combineFiles以那些存在的文件为条件?

感谢。

1 个答案:

答案 0 :(得分:2)

我是Ruffus的开发者。我不确定我完全理解你想要做什么,但是这里有:

为了运行管道的下一阶段而等待不同时间完成的工作正是Ruffus所关注的,所以希望这很简单。

第一个问题是你知道前面创建了哪些文件,即在管道运行之前?让我们假设你这样做。

from ruffus import *
filenames = ["one.file", "two.file", "three.file"]

让我们编写一个虚拟函数,每次调用它时都会创建一个文件。在Ruffus中,任何输入和输出文件名分别包含在前两个参数中。我们没有输入文件名,所以我们的函数调用应该如下所示:

create_file(None, "one.file")
create_file(None, "two.file")
create_file(None, "three.file")

create_file的定义如下所示:

@files([(None, fn) for fn in filenames])
def create_file(no_input_file_name, output_file_name):
    open(output_file_name, "w").write("dummy file")

这些文件中的每一个都将在3次单独的create_file调用中创建。如果您愿意,可以并行运行。

pipeline_run([create_file], multiprocess = 5)

现在要合并文件。确实为此设置了“@Merge”装饰器。我们只需要将它链接到上一个函数:

@merge(create_file, "merge.file")
def merge_file(input_file_names, output_file_name):
    output_file = open(output_file_name, "w")
    for i in input_file_names:
        output_file.write(open(i).read())

只有在对create_file()的三次调用中准备好所有文件时,才会调用merge_file。

整个代码如下:

from ruffus import *
filenames = ["one.file", "two.file", "three.file"]

from random import randint
from time import sleep

@files([(None, fn) for fn in filenames])
def create_file(no_input_file_name, output_file_name):
    # simulate create file process of indeterminate complexity
    sleep(randint(1,5))
    open(output_file_name, "w").write("dummy file")

@merge(create_file, "merge.file")
def merge_file(input_file_names, output_file_name):
    output_file = open(output_file_name, "w")
    for i in input_file_names:
        output_file.write(open(i).read())


pipeline_run([merge_file], multiprocess = 5)

这就是结果:

>>> pipeline_run([merge_file], multiprocess = 5)

    Job = [None -> two.file] completed
    Job = [None -> three.file] completed
    Job = [None -> one.file] completed
Completed Task = create_file
    Job = [[one.file, three.file, two.file] -> merge.file] completed
Completed Task = merge_file