问题
将这两种方法从python2转换为python3时时报错。
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
解决方法
要使代码在Python 3中工作,需要解决两种主要类型的问题。
最大的问题是字符串和字节不再由Python 3中的相同类型表示str类型用于Unicode字符串, bytes类型用于二进制数据。 您的data参数看起来可能应该是bytes (因为您是直接在套接字上发送它的)。 如果确实要支持Unicode字符串,则需要通过某种编码(例如"UTF-8" ) encode()它们进行编码(),然后再通过套接字发送它们。
无论如何,假设data是一个bytes实例,则需要对代码进行一些小的更改,以解决一些API对于str和bytes不同工作方式:
对bytes迭代会产生各个字节的值,但会产生一个整数,而不是一个字符的字符串。 这基本上意味着您不需要在print调用中使用ord ,也不需要在recv的第一部分中使用ord 。
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几行代码(不需要l0和l1 )。