泡菜不兼容扭曲?

时间:2013-03-29 00:49:37

标签: python twisted pickle

我做了两个申请: 客户端从sql server(10k行)中提取数据,并通过套接字将每行pickle发送到“collector”服务器。 服务器使用twisted(这是必需的)并接收每一行,取消它并将数据存储在另一个sql server中。

每次我开始从客户端向服务器发送数据时,在前200行(每次不同的行)服务器会抛出异常: 有时候它会像:

Traceback (most recent call last):
  File "collector2.py", line 81, in dataReceived
    self.count,account  = pickle.loads(data)
  File "/usr/lib/python2.6/pickle.py", line 1374, in loads
    return Unpickler(file).load()
  File "/usr/lib/python2.6/pickle.py", line 858, in load
    dispatch[key](self)
  File "/usr/lib/python2.6/pickle.py", line 1138, in load_pop
    del self.stack[-1]
IndexError: list assignment index out of range

但并不是每次都一样。打印我的红色异常: 例外:从空列表中弹出 例外:列表索引超出范围 例外:“'” 例外:列表分配索引超出范围

另一个奇怪的错误是: 在find_class中输入文件“/usr/lib/python2.6/pickle.py”,第1124行     导入(模块)的 exceptions.ImportError:没有名为ond'

的模块
for i in listaSAI:
    crm={}
    try:
        crm['uid']=i[0]
    except:
        crm['uid']=None
    try:
        crm['type_cond']=i[01]
    except:
        crm['type_cond']=None
    try:
        crm['population_id']=i[2]
    except:
        crm['population_id']=None
    try:
        crm['product_id']=i[3]
    except:
        crm['product_id']=None
    try:
        crm['a_id']=i[4]
    except:
        crm['a_id']=None
    try:
        crm['status']=i[5]
    except:
        crm['status']=None
    #time.sleep(0.001)
    serialized = pickle.dumps((count,crm))
    #print "sent num", count, crm
    s.sendall(serialized)
    count += 1

我的服务器:

def dataReceived(self, data):
    try:
        self.count,account  = pickle.loads(data)        
    except Exception as e:
        print "Eccezione:", e
        print self.count+1
        print "DISAGIO", data
        print traceback.print_exc()

在我的客户端打印数据告诉我一切正常。 如果我尝试在我的客户端中使用time.sleep(0.01)来减慢发送过程,那么一切都很精细,并且没有异常。

我可以做些什么来调试我的代码?

P.S。 我怀疑exception.ImportError:没有名为ond的模块'指的是crm中的“type_cond”键。

2 个答案:

答案 0 :(得分:1)

由于在写入之间添加延迟时没有问题,很明显问题与pickle无关,而是与数据的传输有关。

一种选择是客户端继续以比服务器处理数据更快的速度向套接字写入数据,从而导致缓冲区溢出和数据包丢失。

或者,您是否有多个线程可能同时写入套接字?

答案 1 :(得分:1)

您的协议没有框架,并且您尝试使用SOCK_STREAM(TCP连接),就好像它是面向数据报的(即,像SOCK_DGRAM一样,如UDP)。

因此,您发送一些构成完整pickle数据集的字节,但服务器不知道特定pickle数据集的开始或结束位置。相反,接收代码试图解开任何随机传递给它的字节块。

正如您所发现的,这有时会起作用。但是,无法保证您传递给sock.sendall的字节将作为单个组传递到dataReceived。您必须添加框架,以便接收器可以发现消息边界。有几种方法可以解决这个问题。一种方法是添加长度前缀。然后接收器知道要等待多少字节,并且当它收到正确的号码时可以取消它们。

当然,您永远不应该破坏通过网络接收的数据。看http://docs.python.org/2/library/pickle.html上的大红框?它就在那里,因为如果您编写的服务器就像您在这里展示的那样,那么您已经编写了一个服务器,其中包含一个远程任意代码漏洞,足以驱动半穿过。

由于您的数据看起来相当简单和有条理,我建议您先查看AMP