2015-07-16 2 views
0

Я пытаюсь обновить код, написанный на python2, так что он работает в python3 и все еще работает в python2. Это фрагмент кода в вопросе, который работает под python2:Объединение байтов для создания ctypes.c_char_p строки

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, что блоки ничего простого.

Есть ли лучший способ сделать это, что одна строка, которая работает как в python2 и Python3 (исключения не требуется)

+1

2.6+ имеет ' bytearray', который повторяется как целые числа. У этого также есть 'b''' литералы. Для части форматирования в Python 3 вы можете использовать строку, а затем закодировать ее, что безвредно для Python 2. Например: 'dst = bytearray (пакет [: 6]);' 'self.dst = b ':'. join ([('% 02x'% октет) .encode ('ascii') для октета в dst]) ' – eryksun

+0

Казалось, что он делает работу, намного чище и хорошо играет между python2 и python3. Спасибо за это, я не понимаю, как я отмечаю это как ответ. –

+0

Форматирование 'bytes' является общей проблемой в Python 3. Вы искали ранее ответившие вопросы? BTW, в 3.5 'b '% 02x'% n', наконец, реализовано (т. Е. Определено« bytes .__ mod__ »). – eryksun

ответ

0

Я не знаю, почему я не могу отметить правильный ответ, как таковой, но eryksun Отклик для меня:

2.6+ имеет тип bytearray, который итерации целые. Он также имеет литералы b''. Для части форматирования в Python 3, вы можете использовать строку, а затем кодировать его, которая безвредна в Python 2. Например:

dst = bytearray(packet[:6]); 
self.dst = b':'.join([('%02x' % o).encode('ascii') for o in dst])` 

- eryksun 16 июля в 15:39

+0

Комментарии не являются ответами. Я хотел, чтобы вы искали ответы на похожие вопросы, так как это распространенная проблема в Python 3. Мне не нравится делать работу на ногах самостоятельно. «Ограничительная проблема [ctypes» не имеет отношения к этому вопросу. – eryksun

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