python - 在 Python 中动态创建类时 exec 与 type

标签 python pickle luigi dynamic-class-creation

我有一个 luigi 管道。我们有很多很多定期更改的外部文件,我们希望能够从元数据构建管道。

我动态创建类,并找到了两种方法:

使用执行:

exec("""
class {system}(DeliverySystem):
    pass
""".format(system='ClassUsingExec'))

使用类型:

name = 'ClassUsingType'
globals()[name] = type(name, (DeliverySystem,),{})

这两个在单线程环境中都工作得很好,但是当我开始运行 luigi 并让许多工作进程生成子进程时,exec 版本很好,但类型版本给出了错误,如 this post 中所述。和 this post (请参阅它们以获取更完整的堆栈跟踪):

PicklingError: Can't pickle <class 'abc.ClassUsingType'>: attribute lookup abc.ClassUsingType failed.

我能找到的两者之间唯一的区别是模块:

print(ClassUsingExec.__dict__) #=>

mappingproxy({'__module__': '__main__',
              '__doc__': None,
              '__abstractmethods__': frozenset(),
              '_abc_impl': <_abc_data at 0x15b5063c120>,
              '_namespace_at_class_time': ''})


print(ClassUsingType.__dict__) #=>

mappingproxy({'__module__': 'abc',
              '__doc__': None,
              '__abstractmethods__': frozenset(),
              '_abc_impl': <_abc_data at 0x15b3f870450>,
              '_namespace_at_class_time': ''})

模块似乎不同,这可能是差异的来源。

使用Python 3.6、Windows 10、luigi 2.8.9。

问题:

有没有办法使用type创建一个类,使其模块是定义它的模块,而不是在abc中?

这些方法之间还有我遗漏的其他区别吗?根据this post应该没有区别,但我发现情况并非如此。

最佳答案

出现问题的原因是:

  • 在 Windows 中,子进程无权访问父变量。
  • Luigi Tasks 使用 Register(以及 ABC 的扩展)作为其元类。
  • 动态创建一个以 ABC(抽象基类)作为元类的类时,该类的模块将为 abc,而不是定义该类的模块。

当一个worker被分配一个Task时,它会去该模块加载该任务。由于该模块设置为 abc 而不是动态创建该类的模块,因此它将失败。

要使其工作,所需要做的就是修改类创建来修改模块:

type(name, (DeliverySystem,),{})

变成了

type(name, (DeliverySystem,),{'__module__':__name__})

现在,当工作人员被分配任务时,它将进入正确的模块并重新创建类,一切都会正常!

关于python - 在 Python 中动态创建类时 exec 与 type,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58711025/

相关文章:

python - Pickle vs 输出到 python 中的文件

基于 Python 的异步工作流模块 : What is difference between celery workflow and luigi workflow?

python - 我想提取 QSTS_ID 列并用句号分隔并将其作为单独的列附加到现有列表中

python - 使用 chrome POSTMAN 测试 http POST 时,它在 django 中不起作用

python - popen完成后做一些事情

python - django dj-database-url 运行速度极慢

python - 如何仅加载 pickle 文件中选定的对象?

python - 无法使用 SqlAlchemy pickle 对象错误

python - Luigi 工作流中的 MySQL 目标

python - Luigi中如何只允许特定机器运行任务