序列化Python类

时间:2015-12-31 09:04:07

标签: python python-2.7 serialization apache-spark

我有一个示例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和ovverride一些方法,生活很简单。虽然Python是如此简单但我无法找到一种方法来序列化这个类的对象。

这个类应该可以通过网络进行序列化,因为这个调用的对象是apache spark,它通过网络分配对象。

最好的方法是什么。

我还发现了this,但不知道这是否是最佳方式。

我也读过

  

无法对类,函数和方法进行pickle - 如果你挑选一个对象,那么对象的类不会被pickle,只是一个标识它所属的类的字符串。

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

PS:由于数据量巨大,因此该类将有数百万个对象。因此,请提供2个解决方案,一个最简单,最有效的方法。

编辑:

为了澄清,我必须使用像

这样的东西
def myfun():
    **Some Logic **
    t1 = bean(<params>)
    t2 = bean(<params2>)
    temp = list()
    temp.append(t1)
    temp.append(t2)
    return temp

现在最终如何调用

PairRDD.map(myfun).collect()

抛出异常

<function __init__ at 0x7f3549853c80> is not JSON serializable

2 个答案:

答案 0 :(得分:3)

首先,对于你的例子,泡菜将很有效。 pickle没有序列化&#34;功能&#34;,它只序列化&#34;数据&#34; - 所以,如果你有类型的尝试在远程脚本上序列化,即如果你有类型&#34; bean&#34;在接收端导入 - 您可以使用pickle或cpickle,一切都会正常工作。上述免责声明声明它不保留课程的代码,这意味着如果您没有它在接收端导入,泡菜不会为你工作。

所有跨语言序列化解决方案(即jsonxml)永远不会提供转移类&#34;代码&#34;因为没有合理的方式来代表它。如果你在两端都使用相同的语言(比如这里),有办法让它工作 - 例如你可以marshal对象,腌制结果,发送它,接收端接收,unpickle和unmarshal,你有一个对象的功能 - 这实际上是发送代码和eval() - 它在接收端..

以下是基于您的酸洗对象类的简单示例:

<强> test.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])

运行它:

ben@ben-lnx:~$ python test.py 
1 2|5 6

所以只要您拥有导入的类型,就可以看到pickle工作..

答案 1 :(得分:1)

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

虽然PySpark会自动分配闭包内引用的变量和函数,但是分配模块,库和类是您的责任。如果简单类创建一个单独的模块并通过SparkContext.addPyFile传递它应该就够了:

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

sc.addPyFile("some_module.py")