我正在尝试升级一些用python2编写的代码,因此它可以在python3中运行并且仍然可以在python2中运行。这是在python2下运行的代码片段:
import ctypes
import struct
class Ethernet(ctypes.Structure):
_fields_ = [('dst', ctypes.c_char_p)]
def __init__(self, packet):
(dst, ) = struct.unpack('!6s', packet[:6])
self.dst = ':'.join(['%02x' % (ord(octet), ) for octet in dst])
def main():
p = b'\xab\xad\xba\xbe\x0f\xe9'
e = Ethernet(p)
if b"ab:ad:ba:be:0f:e9" == e.dst:
print(True)
else:
print(False)
if __name__ == '__main__':
main()
当我移动到python3时,我的问题开始了,我得到了相同代码的警告:
File "test2.py", line 11, in <listcomp>
self.dst = ':'.join(['%02x' % (ord(octet), ) for octet in dst])
TypeError: ord() expected string of length 1, but int found
很明显,这段代码在python3中不起作用。
我能让它发挥作用的唯一方法就是这样:
try: # Python 3
self.dst = b':'.join([struct.pack('bb', ord('{:x}'.format((octet >> 4) & 0xf)), ord('{:x}'.format((octet >> 0) & 0xf))) for octet in dst])
except TypeError: # Python 2
self.dst = ':'.join(['%02x' % (ord(octet), ) for octet in dst])
这是非常混乱的,但我尝试的每一种方式都是ctypes.c_char_p的 fields 定义阻止任何简单的事情。
有没有更好的方法可以在python2和python3中运行单行(不需要例外)