gpt4 book ai didi

python - 在 Python 中动态创建类时执行 vs 类型

转载 作者:太空宇宙 更新时间:2023-11-03 23:52:58 26 4
gpt4 key购买 nike

我有一个 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__})

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

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

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com