2013-05-01 3 views
1

Вот код, вызывающий эту ошибку.EOF Ошибка при травлении в python

отправка нить:

data = pickle.dumps (object); 

получения резьбы:

self.object = pickle.loads(data) // Erroneous line 

Ошибка отображаемая

self.object = pickle.loads(data) 
EOFError 

Кроме того, чтобы добавить к деталям, эта ошибка возникает только 50% от времени , Другие 50% случаев, нет ошибки!

+0

Вы уверены, что получили все байты для рассола на принимающем потоке? –

+0

@Martijin Pieters Вы предлагаете, я должен поставить вызов сна перед травлением, чтобы дать достаточно времени для поступления всех байтов? –

+0

Я предлагаю вам убедиться, что все данные были получены до передачи функции 'pickle.loads'. –

ответ

5

С учетом комментариев у меня есть догадка о , скорее всего, проблема, но есть, по крайней мере, 50% шанс, я догадался неправильно, и в этом случае ... скажите мне, и я удалю ответ.

Я предполагаю, что вы пытаетесь использовать сокет потока, как если бы это была последовательность сообщений. Это очень распространенная проблема среди новичков сетевого программирования.

Представьте отправителя делает что-то вроде этого:

data = pickle.dumps(object); 
self.sock.sendall(data) 

И приемник делает что-то вроде этого:

data = self.sock.recv(4096) 
self.object = pickle.loads(data) 

Это может работать 99% времени в простых тестах, но в реальном масштабе использование в мире не сработает. Вы получите частичные сообщения или несколько сообщений в одном вызове или какую-нибудь забавную комбинацию из вышеперечисленного (например, половину сообщения 2, все сообщение 3 и третье сообщение 4).

Итак, вы передадите частичное сообщение на номер loads и вернетесь с сообщением о том, что это не полный рассол.

Это не потому, что что-то сломано; вот как это предположительно для работы. Сокет (TCP) представляет собой поток : последовательность байтов, а не последовательность сообщений. Любая структура, которую вы хотите, помимо этого, вы должны встраивать в данные.

Это означает, что вам необходимо разработать и реализовать протокол, чтобы узнать, когда будет завершено каждое сообщение. Простейшие протоколы - это, вероятно, строки (очевидно, полезны только в том случае, если сообщение никогда не может иметь невыбранную новую строку) и netstrings, но все, что дает вам однозначный способ взглянуть на некоторые данные и сказать «Это сообщение 0, это сообщение 1 и т. Д. «. будет работать.

Обычно это означает добавление полученных данных в некоторый буфер и циклическое перемещение сообщений в этом буфере. Например, с линиями, вместо этого:

while True: 
    line = sock.recv(4096) 
    do_stuff(line) 

... вам это нужно:

rdbuf = '' 
while True: 
    rdbuf += sock.recv(4096) 
    lines = rdbuf.split('\n') 
    rdbuf = lines[-1] 
    for line in lines[:-1]: 
     dostuff(line) 

Если вы думаете об этом, это ничем не отличается от файла. Представьте себе этот код:

with open('foo.data', 'wb') as f: 
    f.write('123') 
    f.write('45') 
with open('foo.data', 'rb') as f: 
    while True: 
     number = f.read() 

Это будет читать '12345', а не '123'.Если вы хотите получить '123', вам нужно знать, как читать только 3 байта. Приклеивание префикса длины или добавление пробелов в качестве разделителя или просто наличие внешних знаний о том, что первое число всегда равно 3 цифрам ... ничего работает, но вам нужно сделать что-то.

Смежные вопросы