【发布时间】:2018-07-14 21:32:53
【问题描述】:
我正在使用 PySpark 处理一些通话数据。如您所见,我通过使用元类动态地将一些内部类添加到类GetInfoFromCalls。
以下代码位于包for_test 中,存在于所有节点中:
class StatusField(object):
"""
some alias.
"""
failed = "failed"
succeed = "succeed"
status = "status"
getNothingDefaultValue = "-999999"
class Result(object):
"""
Result that store result and some info about it.
"""
def __init__(self, result, status, message=None):
self.result = result
self.status = status
self.message = message
structureList = [
("user_mobile", str, None),
("real_name", str, None),
("channel_attr", str, None),
("channel_src", str, None),
("task_data", dict, None),
("bill_info", list, "task_data"),
("account_info", list, "task_data"),
("payment_info", list, "task_data"),
("call_info", list, "task_data")
]
def inner_get(self, defaultValue=StatusField.getNothingDefaultValue):
try:
return self.holder.get(self)
except Exception as e:
return Result(defaultValue, StatusField.failed)
print(e)
class call_meta(type):
def __init__(cls, name, bases, attrs):
for name_str, type_class, pLevel_str in structureList:
setattr(cls, name_str, type(
name_str,
(object,),
{})
)
class GetInfoFromCalls(object, metaclass = call_meta):
def __init__(self, call_deatails):
for name_str, type_class, pLevel_str in structureList:
inn = getattr(self.__class__, name_str)()
object_dict = {
"name": name_str,
"type": type_class,
"pLevel": None if pLevel_str is None else getattr(self, pLevel_str),
"context": None,
"get": inner_get,
"holder": self,
}
for attr_str, real_attr in object_dict.items():
setattr(inn, attr_str, real_attr)
setattr(self, name_str, inn)
self.call_details = call_deatails
我跑的时候
import pickle
pickle.dumps(GetInfoFromCalls("foo"))
它引发了这样的错误:
Traceback (most recent call last):
File "<ipython-input-11-b2d409e35eb4>", line 1, in <module>
pickle.dumps(GetInfoFromCalls("foo"))
PicklingError: Can't pickle <class '__main__.user_mobile'>: attribute lookup user_mobile on __main__ failed
似乎我不能腌制内部类,因为它们是由代码动态添加的。当类被腌制时,内部类不存在,对吗?
真的,我不想编写这些彼此几乎相同的类。有人有避免这个问题的好方法吗?
【问题讨论】:
-
Upovted,因为看到 MCVE 总是很高兴,但老实说,我不明白,到底为什么你会选择如此复杂的解决方案。尤其是使用 Spark。
-
MCVE 是什么意思 :) ?因为我在 jupyter notebook 中使用 PySpark,所以我一直使用
TAB给我一些提示,比如call_detal_info.bill_info.get()。我知道重写一些像__getattr__()这样的魔术方法可以解决我的问题,但是我只想知道在酸洗和解酸的情况下使用元类是否可行? -
MCVE 是minimal reproducible example :) 如果您只想要
.语法,为什么不使用namedtuple?你真的想在运行时生成类,那么我会在外部范围内使用type来完成。与namedtuple相同。 -
namedtuple或type在模块范围内有同样的问题,除非我编写像s = type("s", (object, ), {})这样的代码。这不是我真正关心的:)。
标签: python-3.x metaprogramming pickle metaclass