创建 Luigi 任务图时出现 JSON 序列化错误

Posted

技术标签:

【中文标题】创建 Luigi 任务图时出现 JSON 序列化错误【英文标题】:JSON serialization error when creating a Luigi task graph 【发布时间】:2017-11-06 20:14:42 【问题描述】:

我正在尝试使用 Luigi 批量处理几个 Jupyter 笔记本,但遇到了问题。

我有两节课。第一个,transform.py

import nbformat
import nbconvert

import luigi
from nbconvert.preprocessors.execute import CellExecutionError


class Transform(luigi.Task):
    """Foo."""
    notebook = luigi.Parameter()
    requirements = luigi.ListParameter()

    def requires(self):
        return self.requirements

    def run(self):
        nb = nbformat.read(self.notebook, nbformat.current_nbformat)
        # https://nbconvert.readthedocs.io/en/latest/execute_api.html
        ep = nbconvert.preprocessors.ExecutePreprocessor(timeout=600, kernel_name='python3')
        try:
            ep.preprocess(nb, 'metadata': 'path': "/".join(self.notebook.split("/")[:-1]))
            with self.output().open('w') as f:
                nbformat.write(nb, f)
        except CellExecutionError:
            pass  # TODO

    def output(self):
        return luigi.LocalTarget(self.notebook)

这定义了一个将笔记本作为输入的 Luigi 任务(以及运行此任务的可能的先前要求),并且应该运行该笔记本并报告成功或失败作为输出。

要运行 Transform 任务,我有一个很小的 ​​Runner 类:

import luigi


class Runner(luigi.Task):
    requirements = luigi.ListParameter()

    def requires(self):
        return self.requirements

为了完成我的小工作,我会这样做:

from transform Transform
trans = Transform("../tests/fixtures/empty_valid_errorless_notebook.ipynb", []) 
from runner import Runner
run_things = Runner([trans])

但这引发了TypeError: Object of type 'Transform' is not JSON serializable

我的luigi 任务格式是否正确?如果是这样,run 中的哪个组件使整个类不可序列化是否很明显?如果没有,我应该如何调试?

【问题讨论】:

【参考方案1】:

requires() 应该返回一个或多个任务,而不是参数。

例如,

class Runner(luigi.Task):
  notebooks = luigi.ListParameter()

  def requires(self):
    required_tasks = []  
    for notebook in self.notebooks:
      required_tasks.append(Transform(notebook))
    return required_tasks

class Transform(luigi.Task):
   notebook = luigi.Parameter()

   def requires(self):
      return []

# then to run at cmd line
luigi --module YourModule Runner --noteboooks '["notebook1.pynb","notebook2.pynb"]' 

【讨论】:

所以不可能不提前硬编码依赖关系? 不确定您的意思...您可以对其进行硬编码,我只是指出 requires() 方法的预期返回类型是什么。如果您需要另一个示例,请告诉我。 我想在运行时以编程方式创建一个新任务,将任何额外的要求从上面传递下去。所以假设我在运行时决定我的任务图是 Transform("a.ipynb") --> Transform("b.ipynb") --> Runner。 Runner 需要能够创建trans_a = Transform("a.ipynb", requirements=[])Transform("b.ipynb", requirements=[trans_a])。如果我不能将 requirements 参数作为变量写入,我不确定我该怎么做(至少没有文件 I/O 技巧)。 不确定“运行时”是什么意思。您将传入动态生成任务所需的笔记本列表和其他参数,而不是任务本身作为参数。

以上是关于创建 Luigi 任务图时出现 JSON 序列化错误的主要内容,如果未能解决你的问题,请参考以下文章

Newtonsoft.Json.JsonSerializationException:'反序列化对象时出现意外标记:使用动态对象注释

使用 NSDictionary 访问 JSON 序列化时出现异常

使用 GSON 序列化时出现“声明多个 JSON 字段命名”错误

在 Python 中序列化 JSON 时出现“TypeError: (Integer) is not JSON serializable”?

反序列化类时出现“Newtonsoft.Json.JsonSerializationException 无法找到用于类型的构造函数”错误

Spring boot,Jackson Json 在序列化和反序列化时出现问题