我有一条路易吉管道。我们有很多经常变化的外部文件,我们希望能够从元数据构建管道。你知道吗
我动态创建类,并找到了两种方法:
使用exec:
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': ''})
似乎模块是不同的,这可能是差异的来源
使用python3.6、windows10、luigi2.8.9。你知道吗
问题:
有没有办法用type
来创建一个类,使它的模块是定义它的模块,而不是在abc
中?你知道吗
这两种方法之间还有什么不同之处吗?根据this post,应该没有区别,但我不认为是这样。你知道吗
出现问题的原因是:
ABC
(抽象基类)为元类的类时,该类的模块将是abc
,而不是定义该类的模块的名称。你知道吗当一个工人被分配一个任务时,它将进入模块来加载任务。由于模块被设置为
abc
,而不是动态创建类的模块,因此它将失败。你知道吗要使其正常工作,只需修改类创建以修改模块:
变成
现在,当工人被分配任务时,它将进入正确的模块并重新创建类,一切都将正常工作!你知道吗
相关问题 更多 >
编程相关推荐