【问题标题】:cPickle.UnpicklingError: pickle data was truncatedcPickle.UnpicklingError:泡菜数据被截断
【发布时间】:2012-01-02 20:13:03
【问题描述】:

我使用远程过程调用在两个进程之间进行通信。我将对象从手上发送到另一个。该对象是 django 模型的对象。对象有不同的变量、整数和字符串。

如果我只更改整数变量,一切正常。如果我第一次更改字符串变量它也可以工作,但是如果我第二次更改字符串我的代码崩溃并且我收到以下错误消息

Traceback (most recent call last):
  File "/home/manch011/disserver/src/disserver/gui/backends/receiver.py", line 69, in run
    name, args, kwargs = cPickle.load(connFile)
cPickle.UnpicklingError: pickle data was truncated

这是我的代码, 在服务器端:

_exportedMethods = {
    'changes': signal_when_changes,
}  

class ServerThread(QtCore.QThread):

    def __init__(self):
        super(ServerThread,self).__init__()
        st = self
    #threading.Thread.__init__(self)
    def run(self):
        HOST = ''     # local host
        PORT = 50000
        SERVER_ADDRESS = HOST, PORT

        # set up server socket
        s = socket.socket()
        s.bind(SERVER_ADDRESS)
        s.listen(5)

        while True:
            conn, addr = s.accept()
            connFile = conn.makefile()
            name, args, kwargs = cPickle.load(connFile)
            res = _exportedMethods[name](*args,**kwargs)
            cPickle.dump(res,connFile) ; connFile.flush()
            conn.close()

这是客户端:

class RemoteFunction(object):
def __init__(self,serverAddress,name):
    self.serverAddress = serverAddress
    self.name = name
def __call__(self,*args,**kwargs):
    s = socket.socket()
    s.connect(self.serverAddress)
    f = s.makefile()
    cPickle.dump((self.name,args,kwargs), f) 
    f.flush()
    res = cPickle.load(f)
    s.close()
    return res

def machine_changed_signal(machine):
    HOST = ''
    PORT = 50000
    SERVER_ADDRESS = HOST, PORT
    advise = RemoteFunction(SERVER_ADDRESS,'changes')
    advise(machine)

我不熟悉 cPickle,因此无法弄清楚这一点,有人可以向我解释一下吗?

提前致谢

【问题讨论】:

    标签: python sockets django-models rpc pickle


    【解决方案1】:

    我解决了自己的问题。但首先我在问题中描述的错误信息没有意义。

    我是新解决的问题,并且使用了 Pyro4 框架。所以我收到了一条新的错误消息,它与旧的但很清楚。你不能腌制类对象。 因为在我的情况下我只需要属性值,所以我将它传递给一个简单的字典。

    首先下载Pyro4并安装 一个简单的例子,类似于Pyro homepage上的例子:

    # saved as helloworld.py
    import Pyro4
    import threading
    import os
    class HelloWorld(object):
        def get_hello_world(self, name):
            return "HelloWorld,{0}.".format(name)
    
    #The NameServer had to run in a own thread because he has his own eventloop
    class NameServer(threading.Thread):
        def __init__(self):
        threading.Thread.__init__(self)
        def run(self):
        os.system("python -m Pyro4.naming")
    ns = NameServer()
    ns.start()
    hello_world=HelloWorld()
    daemon=Pyro4.Daemon()                 # make a Pyro daemon
    ns=Pyro4.locateNS()                   # find the name server
    uri=daemon.register(hello_world)   # register the greeting object as a Pyro object
    ns.register("example.helloworld", uri)  # register the object with a name in the name server
    print "Ready."
    daemon.requestLoop()                  # start the event loop of the server to wait for calls
    

    运行这个程序,然后执行下一个

    # saved as client.py
    import Pyro4
    name=raw_input("What is your name? ").strip()
    helloworld=Pyro4.Proxy("PYRONAME:example.helloworld")    # use name server object lookup uri shortcut
    print helloworld.get_hello_world(name)
    

    重要的是你不能传输类实例。所以“name”不能是类实例。

    【讨论】:

    • 您能否添加一些代码,或者您如何解决问题的示例?如果链接断开或失效,则此帖子中没有任何信息可以帮助未来的观众。
    • 是的,这就是我所追求的——我个人不需要它,但其他人可能需要它,这将更有帮助。感谢您这么快发布。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-21
    • 2011-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多