2017-03-13 117 views
0

在將這兩種方法從python2轉換爲python3時遇到了一些麻煩。Python 2 to python 3

Python2:

def send(self, data): 
    if self.debug: 
     print 'Send:', 
     print ':'.join('%02x' % ord(c) for c in data) 
    l0 = len(data) & 0xFF 
    l1 = (len(data) >> 8) & 0xFF 
    d = chr(l0) + chr(l1) + data 
    self.sock.send(d) 

def recv(self): 
    data = self.sock.recv(2) 
    l0 = ord(data[0]) 
    l1 = ord(data[1]) 
    plen = l0 + (l1 << 8) 
    data = self.sock.recv(plen) 
    if self.debug: 
     print 'Recv:', 
     print ':'.join('%02x' % ord(c) for c in data) 
    return data 

的Python 3這是我走到這一步:

def send(self, data): 
    if self.debug: 
     print('Send:', end=' ') 
     print(':'.join('%02x' % ord(c) for c in data)) 
    l0 = len(data.encode('utf-8')) & 0xFF 
    l1 = (len(data.encode('utf-8')) >> 8) & 0xFF 
    d = chr(l0) + chr(l1) + data 
    self.sock.send(d) 

def recv(self): 
    data = self.sock.recv(2) 
    l0 = ord(data[0]) 
    l1 = ord(data[1]) 
    plen = l0 + (l1 << 8) 
    data = self.sock.recv(plen) 
    if self.debug: 
     print('Recv:', end=' ') 
     print(':'.join('%02x' % ord(c) for c in data)) 
    return data 

我不斷收到此錯誤:

TypeError: ord() expected string of length 1, but int found 

任何幫助,將不勝感激。謝謝

+0

您是否已經諮詢過['2to3'](https://docs.python.org/3.0/library/2to3.html)工具?引發錯誤的問題在於你有一個'bytes'對象而不是'str',它在迭代時直接給出了整數,因此不需要調用'ord'。 –

回答

2

主要有兩種類型的問題你需要解決以使您的代碼在Python 3中工作。

最大的問題是字符串和字節不再由Python 3中的相同類型表示。str類型是對於Unicode字符串,bytes類型用於二進制數據。您的data參數看起來應該可能是bytes(因爲您直接通過套接字發送它)。如果您確實想要支持Unicode字符串,則需要使用某些編碼(例如"UTF-8")將它們encode()發送給它們,然後通過套接字發送它們。

無論如何,假設databytes例如,你需要做一些小的改動的代碼,以解決少數的API如何爲strbytes工作不同:在bytes

  1. 迭代產生單個字節值,但是作爲整數,而不是一個字符的字節串。這基本上意味着您不需要在print調用中的ord,也不需要在recv的第一部分中。

  2. chr函數創建str而不是bytes實例,並且不能將不同類型連接在一起。從一個整數創建一個bytes實例有點尷尬(bytes(some_number)不能做你想做的),但這是可能的。

你有的另一個問題是更容易理解。在Python 3中,print是一個函數而不是語句,所以你需要圍繞它的參數使用括號。它還使用不同的語法來抑制行尾。

這是你的代碼的完全固定的版本:

def send(self, data): 
    if self.debug: 
     print('Send:', end='')      # new way to suppress the newline 
     print(':'.join('%02x' % c for c in data)) # add parentheses, no need for ord 
    l0 = len(data) & 0xFF 
    l1 = (len(data) >> 8) & 0xFF 
    d = bytes([l0, l1]) + data      # build prefix bytestring differently 
    self.sock.send(d) 

def recv(self): 
    l0, l1 = self.sock.recv(2)    # no need for ord, unpack directly as ints 
    plen = l0 + (l1 << 8) 
    data = self.sock.recv(plen) 
    if self.debug: 
     print('Recv:', end='') 
     print(':'.join('%02x' % c for c in data)) 
    return data 

注意,struct模塊可以提供編碼一個更優雅的方式和你的數據的長度解碼的字節串。例如,struct.pack("<H", len(data))可以代替send中的幾行代碼(您不需要l0l1)。

+0

'幫助(字節)'表示「_bytes(iterable_of_ints) - > bytes_」和「_bytes(int) - >字節對象的大小由參數初始化爲null bytes_」給出一個單字節的字節對象,字節([num])'而不是'bytes(num)' –

+0

@ TadhgMcDonald-Jensen:是的,這就是我所說的尷尬。不需要'bytes([l0])+ bytes([l1])''。您可以從列表中創建一個預先concatenated的字符串,其中包含整數。 'struct.pack'函數甚至更好(儘管看起來我得到了所需字節序的符號錯誤)。 – Blckknght

+0

是的,但你從來沒有真正說明爲什麼'字節(num)'不會產生一個字節,只是它不這樣做。我想我應該提及它實際上對OP做了什麼(發生在我身上我應該從頭開始說)但這是一個很好的答案。 –

0

insteed打印的使用打印(一),如: 蟒蛇2.X:

def send(self, data): 
    if self.debug: 
     print 'Send:', 
     print ':'.join('%02x' % ord(c) for c in data) 
    l0 = len(data) & 0xFF 
    l1 = (len(data) >> 8) & 0xFF 
    d = chr(l0) + chr(l1) + data 
    self.sock.send(d) 

def recv(self): 
    data = self.sock.recv(2) 
    l0 = ord(data[0]) 
    l1 = ord(data[1]) 
    plen = l0 + (l1 << 8) 
    data = self.sock.recv(plen) 
    if self.debug: 
     print 'Recv:', 
     print ':'.join('%02x' % ord(c) for c in data) 
    return data 

蟒蛇3.X:

def send(self, data): 
    if self.debug: 
     print ('Send:'), 
     print (':'.join('%02x' % ord(c) for c in data)) 
    l0 = len(data) & 0xFF 
    l1 = (len(data) >> 8) & 0xFF 
    d = chr(l0) + chr(l1) + data 
    self.sock.send(d) 

def recv(self): 
    data = self.sock.recv(2) 
    l0 = ord(data[0]) 
    l1 = ord(data[1]) 
    plen = l0 + (l1 << 8) 
    data = self.sock.recv(plen) 
    if self.debug: 
     print ('Recv:'), 
     print (':'.join('%02x' % ord(c) for c in data)) 
    return data