使用Python设计可扩展的管道

时间:2012-07-29 20:41:00

标签: python pipeline

上下文:我目前正在使用Python代码为大型天文成像系统提供数据减少管道。主要管道类通过许多离散处理“阶段”传递实验数据。

这些阶段用单独的.py文件编写,构成一个包。在运行时生成可用阶段列表,以便用户可以选择运行数据的阶段。 此方法的目的是允许用户在将来创建其他阶段。

问题:所有管道配置参数和数据结构(当前)都位于主管道类中。有没有一种简单的方法可以在运行时导入的阶段中访问它们?

我目前的最佳尝试似乎“错误”并且有点原始,因为它使用循环导入和类变量。是否有一种方法可以让管道实例将引用传递给它自己作为它调用的每个阶段的参数?

这是我第一次编写一个大型python项目,而我缺乏设计知识。

非常感谢任何帮助。

4 个答案:

答案 0 :(得分:9)

我建立了一个类似的系统;它被称为collective.transmogrifier。有一天我会把它变得更通用(它目前与CMF有关,是Plone的基础之一)。

解耦

您需要的是一种解耦管道组件注册的方法。在Transmogrifier中,我使用Zope Component Architucture(体现在zope.component包中)。 ZCA允许我注册实现给定接口的组件,然后将这些组件作为序列或名称查找。还有其他方法可以做到这一点,例如,python eggs具有entry points的概念。

关键在于管道中的每个组件都可以通过纯文本名称引用,在构造时取消引用。通过独立于管道包注册自己的组件,可以插入第三方组件以便重复使用。

配置

Transmogrifier管道使用基于python ConfigParser module的文本格式进行配置,其中管道的不同组件被命名,配置和分组在一起。在构造管道时,每个部分因此被赋予配置对象。部分不必集中查找配置,在实例化时配置。

中央州

我还传入了一个代表管道的中央“transmogrifier”实例。如果任何组件需要共享每个管道状态(例如缓存数据库连接以便在组件之间重用),则可以在该中央实例上执行此操作。所以在我的例子中,每个部分都有一个对中央管道的引用。

个人成分和行为

Transmogrifier管道组件是生成器,它使用管道中前面组件的元素,然后生成它们自己处理的结果。因此,组件通常具有前一阶段的参考,但不知道消耗其输出的是什么。我说'一般',因为在Transmogrifier中,一些管道元素可以从外部源生成元素,而不是使用前一个元素。

如果确实需要根据要处理的单个项目更改管道组件的行为,请使用要发现的每个组件的额外信息标记这些项目本身。在Transmogrifier中,项是字典,您可以向使用组件名称的字典添加额外的键,以便每个组件可以查找此额外信息并根据需要更改行为。

摘要

  • 使用基于配置的元素间接查找来解耦管道组件。

  • 当您实例化组件时,请同时配置它们并为它们提供完成工作所需的内容。这可能包括一个中心对象来跟踪特定于管道的状态。

  • 运行管道时,只传递要处理的项目,并让每个组件仅根据该项目的行为进行处理。

答案 1 :(得分:3)

Ruffus是一个python库,旨在让科学和其他分析能够以最少的麻烦和最小的努力实现自动化。“

肯定:它允许增量处理数据,您可以定义非常复杂的序列。此外,任务自动并行化。它允许您打开/关闭功能,并根据您指定的模式自动定义它们的顺序。

否定:根据我的口味,它有时过于pythonic,它只切换和命令功能,而不是例如类。但当然,您可以使用代码初始化每个函数中的类。

出于您的目的,您可以在函数上方使用 @active_if 标识符,以启用它或通过管道禁用它。您可以检索是否要从外部配置文件激活它,您使用 ConfigParser 读取该文件。

为了加载ConfigParser值,您必须编写另一个python模块,该模块初始化ConfigParser实例。必须在管道模块的第一行导入此模块。

答案 2 :(得分:1)

两个选项:

  1. 在其他地方配置:有一个配置模块,并使用django配置系统之类的东西来实现。
  2. 不要让阶段导入管道类,而是在实例化时传递它们一个管道实例。

答案 3 :(得分:1)

我的一位同事从模拟数据(svn checkout https://svn.gforge.hlrs.de/svn//opensesame)开发了类似的天体物理合成发射图管道。

他这样做的方式是:

配置存在于一个单独的对象中(实际上是一个字典)。

阶段是:

  • 在实例化时接收配置对象作为构造函数参数
  • 稍后通过分配获取配置(例如stage.config = config_object)
  • 执行时接收配置对象作为参数(例如stage.exec(config_object,other_params))