序列化Python类

2024-06-28 20:54:43 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个示例Python类

class bean :
    def __init__(self, puid, pogid, bucketId, dt, at) :
    self.puid = puid
    self.pogid = pogid
    self.bucketId = bucketId
    self.dt = (datetime.datetime.today() - datetime.datetime.strptime(dt, "%Y-%m-%d %H:%M:%S")).days
    self.absdt=dt
    self.at = at

现在我知道,在Java中,要使类可序列化,我们只需扩展serializable并覆盖一些方法,这样就很简单了。虽然Python过于简单,但我无法找到序列化此类对象的方法。在

这个类应该在网络上是可序列化的,因为这个调用的对象转到apachespark,它在网络上分发对象。在

最好的办法是什么。在

我也找到了this,但不知道这是否是最好的方法。在

我也读书

Classes, functions, and methods cannot be pickled -- if you pickle an object, the object's class is not pickled, just a string that identifies what class it belongs to.

那么这是否意味着这些类不能被序列化?在

PS:由于数据量巨大,这个类的对象将有数百万个。所以请提供两种解决方案,一种是最简单的,另一种是最有效的。在

编辑:

为了澄清,我不得不用这个

^{pr2}$

现在它终于被称为

PairRDD.map(myfun).collect()

引发异常

<function __init__ at 0x7f3549853c80> is not JSON serializable

Tags: 对象方法self网络datetime序列化initdt
2条回答

首先,以pickle为例,pickle非常有用。pickle不序列化“函数”,它只序列化“数据”-因此,如果您有您试图在远程脚本上序列化的类型,也就是说,如果您在接收端导入了“bean”类型,那么您可以使用pickle或cpickle,并且所有操作都将工作上面提到的免责声明声明它不保留类的代码,意思是如果接收端没有导入,pickle就不适合您。在

所有跨语言序列化解决方案(即jsonxml)永远不会提供传递类“代码”的能力,因为没有合理的方法来表示它。如果您在两端使用相同的语言(如这里),有办法让它工作-例如,marshal对象,pickle结果,发送它,在接收端接收,取消pickle和unmarshal,并且您有一个具有其函数的对象-这实际上是发送代码,eval()-在接收端对其进行处理。。在

下面是一个基于pickle对象类的快速示例:

测试.py

import datetime
import pickle

class bean:
    def __init__(self, puid, pogid, bucketId, dt, at) :
        self.puid = puid
        self.pogid = pogid
        self.bucketId = bucketId
        self.dt = (datetime.datetime.today() - datetime.datetime.strptime(dt, "%Y-%m-%d %H:%M:%S")).days
        self.absdt=dt
        self.at = at
    def whoami(self):
        return "%d %d"%(self.puid, self.pogid)

def myfun():
    t1 = bean(1,2,3,"2015-12-31 11:50:25",4)
    t2 = bean(5,6,7,"2015-12-31 12:50:25",8)
    tmp = list()
    tmp.append(t1)
    tmp.append(t2)
    return tmp

if __name__ == "__main__":
    with open("test.data", "w") as f:
        pickle.dump(myfun(), f)
    with open("test.data", "r") as f2:
        obj = pickle.load(f2)
    print "|".join([bean.whoami() for bean in obj])

运行它:

^{pr2}$

所以你可以看到pickle工作只要你有导入的类型。。在

只要传递给__init__puidpogidbucketIddtat)的所有参数都可以序列化,就不需要任何额外的步骤。如果您遇到任何问题,很可能意味着您没有在集群上正确地分发模块。在

虽然PySpark自动分发闭包中引用的变量和函数,但是分发模块、库和类是您的责任。对于simples类,创建一个单独的模块并通过SparkContext.addPyFile传递它就足够了:

# https://www.python.org/dev/peps/pep-0008/#class-names
from some_module import Bean  

sc.addPyFile("some_module.py")

相关问题 更多 >