以下是導致此錯誤的代碼。EOF Python中酸洗錯誤
發送線程:
data = pickle.dumps (object);
接收線程:
self.object = pickle.loads(data) // Erroneous line
顯示的錯誤是
self.object = pickle.loads(data)
EOFError
另外添加到細節,此錯誤時只有50%的時間的。另外50%的時間,沒有錯誤!
以下是導致此錯誤的代碼。EOF Python中酸洗錯誤
發送線程:
data = pickle.dumps (object);
接收線程:
self.object = pickle.loads(data) // Erroneous line
顯示的錯誤是
self.object = pickle.loads(data)
EOFError
另外添加到細節,此錯誤時只有50%的時間的。另外50%的時間,沒有錯誤!
鑑於評論,我猜測最可能的問題是,但至少有50%的機會我猜錯了,在這種情況下......告訴我,我會刪除答案。
我猜你試圖使用流套接字,就好像它是一個消息序列。這在網絡編程新手中是一個非常普遍的問題。
想象發件人確實是這樣的:
data = pickle.dumps(object);
self.sock.sendall(data)
和接收器確實是這樣的:
data = self.sock.recv(4096)
self.object = pickle.loads(data)
這可能工作的簡單測試,99%的時間,但在現實世界使用它將無法正常工作。您將在一次呼叫中收到部分消息或多條消息,或者收到上述消息的一些有趣組合(如消息2的一半,消息3的全部和消息4的三分之一)。
因此,您會將部分消息傳遞給loads
並返回一個錯誤,告訴您它不是一個完整的pickle。
那不是因爲什麼都壞了;這就是假設工作。一個(TCP)套接字是一個流:一個字節序列,而不是一系列消息。任何你想要的結構,你必須建立數據。
這意味着你必須設計和實現一個協議 - 一種知道每個消息何時完成的方式。最簡單的協議可能是行(顯然只有在消息永遠不會有非轉義的換行符時纔有用),但是任何能夠讓你明確地查看某些數據並且說「這是消息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位數字長... 什麼作品,但你必須做東西。
你確定你收到接收線程上的pickle的所有字節嗎? – 2013-05-01 16:46:53
@Martijin Pieters你是否建議,我應該在酸洗之前進行一次睡眠呼叫,讓所有字節都有足夠的時間到達? – 2013-05-01 16:48:14
我建議你在把它交給'pickle.loads'函數之前確保所有數據都已經到達。 – 2013-05-01 16:50:12