在Python中处理简单工作流
我正在写一段代码,这段代码可以处理一个数据集,并对其运行一些算法。
用户上传一个数据集,然后选择要在这个数据集上运行哪些算法,接着创建一个工作流程,像这样:
workflow =
{0: {'dataset': 'some dataset'},
1: {'algorithm1': "parameters"},
2: {'algorithm2': "parameters"},
3: {'algorithm3': "parameters"}
}
这意味着我会把 workflow[0]
作为我的数据集,然后我会在它上面运行 algorithm1
。接着,我会把这个算法的结果拿来,作为新的数据集,再运行 algorithm2
。然后我会把新的结果再拿来,运行 algorithm3
。这个过程会一直进行,直到最后一个算法为止,而且这个工作流程的长度没有限制。
我是在用Python写这个程序。你能给我一些处理这个工作流程的建议吗?
5 个回答
定义一个叫做 Dataset
的类,用来跟踪你的一组数据。这个类里要定义一些方法。大概是这样的:
class Dataset:
# Some member fields here that define your data, and a constructor
def algorithm1(self, param1, param2, param3):
# Update member fields based on algorithm
def algorithm2(self, param1, param2):
# More updating/processing
接下来,遍历你的 "workflow" 字典。对于第一个条目,简单地创建一个 Dataset
类的实例。
myDataset = Dataset() # Whatever actual construction you need to do
对于后面的每个条目...
- 以某种方式提取键和值(如果可能的话,我建议你改变一下你的工作流数据结构,因为
dict
在这里不太方便) - 把参数字符串解析成一个参数元组(这一步由你决定怎么做)。
假设你现在有了字符串
algorithm
和当前迭代的元组params
...那么就可以用
getattr(myDataset, algorithm)(*params)
来调用。这段代码会在
myDataset
上调用一个函数,函数的名字由 "algorithm" 指定,参数列表则来自 "params"。
如果每个 algorithm
都是对 dataset
中的每个元素进行操作,那么 map()
就是一个很优雅的选择:
dataset=workflow[0]
for algorithm in workflow[1:]:
dataset=map(algorithm, dataset)
比如说,如果你只想计算奇数的平方根,可以使用:
>>> algo1=lambda x:0 if x%2==0 else x
>>> algo2=lambda x:x*x
>>> dataset=range(10)
>>> workflow=(dataset, algo1, algo2)
>>> for algo in workflow[1:]:
dataset=map(algo, dataset)
>>> dataset
[0, 1, 0, 9, 0, 25, 0, 49, 0, 81]
你想在某个数据集上运行一个处理流程。这听起来像是一个归约操作(在某些编程语言中叫做fold)。其实没必要搞得太复杂:
result = reduce(lambda data, (aname, p): algo_by_name(aname)(p, data), workflow)
这假设你的工作流程是这样的(以文本为主,所以你可以用YAML或JSON来加载):
workflow = ['data', ('algo0', {}), ('algo1', {'param': value}), … ]
而你的算法看起来是这样的:
def algo0(p, data):
…
return output_data.filename
algo_by_name这个函数接收一个名字,然后给你一个算法函数;比如说:
def algo_by_name(name):
return {'algo0': algo0, 'algo1': algo1, }[name]
(旧的补充:如果你想要一个写处理流程的框架,可以使用Ruffus。它就像一个构建工具,但支持进度显示,还有漂亮的流程图。)