cPickle.UnpicklingError: pickle 数据被截断
我使用远程过程调用(Remote Procedure Call)来让两个进程之间进行通信。我把对象从一个进程发送到另一个进程。这个对象是一个基于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
1 个回答
1
我自己解决了问题。不过首先,我想说我在提问时描述的错误信息其实没什么意义。
我刚接触这个问题,使用了Pyro4框架。结果我遇到了一个新的错误信息,虽然和之前的错误类似,但更清楚了。你不能把类的对象进行序列化(也就是“打包”)。因为在我的情况下,我只需要属性的值,所以我把这些值放在一个简单的字典里。
首先,你需要下载并安装Pyro4。下面是一个简单的例子,和Pyro主页上的例子类似:
# 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”不能是一个类的实例。