Skip to main content
 首页 » 编程设计

python之cPickle.UnpicklingError : pickle data was truncated

2025年05月04日10傻小

我使用远程过程调用在两个过程之间进行通信。我将对象从手上发送到另一个。该对象是 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,因此无法理解这一点,有人可以向我解释一下吗?

在此先感谢 Chis

请您参考如下方法:

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

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

首先下载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) 

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