Как определить двоичную строку в Python таким образом, чтобы она работала как с py2, так и с py3?

#python #python-3.x #python-2.5

#python #python-3.x #python-2.5

Вопрос:

Я пишу модуль, который должен работать как в Python 2, так и в Python 3, и мне нужно определить двоичную строку.

Обычно это было бы что-то вроде data = b'abc' , но этот код не работает на Python 2.5 с недопустимым синтаксисом.

Как я могу написать приведенный выше код таким образом, чтобы он работал во всех версиях Python 2.5

Примечание: это должно быть binary (оно может содержать любые символы, 0xFF), это очень важно.

Комментарии:

1. Двоичная строка? Вы имеете в виду bytes объект?

2. b"abc" Синтаксис и bytes() конструктор были добавлены в Python 2.6 .

3. Да, я имел в виду байты.

4. При поиске python 2 и python 3 различными способами поиска в Google для этого на первой странице результатов поиска появятся как библиотека six, так и моя книга, в которой есть по существу похожие рабочие решения для этого. Тем не менее, кажется, никто не знает, что любой из них существует. Как мы можем это исправить? Распространяйте информацию!

Ответ №1:

Я бы рекомендовал следующее:

 from six import b
  

Конечно, для этого требуется модуль six.
Если вы этого не хотите, вот другая версия:

 import sys
if sys.version < '3':
    def b(x):
        return x
else:
    import codecs
    def b(x):
        return codecs.latin_1_encode(x)[0]
  

Подробная информация.

Эти решения (по сути, одинаковые) работают, являются чистыми, настолько быстрыми, насколько вы собираетесь получить, и могут поддерживать все 256-байтовые значения (чего не может ни одно из других решений здесь).).

Ответ №2:

Если строка содержит только символы ASCII, вызовите encode . Это даст вам a str в Python 2 (точно так b'abc' же) и a bytes в Python 3:

 'abc'.encode('ascii')
  

Если нет, вместо того, чтобы помещать двоичные данные в исходный код, создайте файл данных, откройте его 'rb' и прочитайте из него.

Комментарии:

1. Как вы и подозревали, у меня есть несколько очень маленьких двоичных блоков, поэтому использование файлов для их хранения не является вариантом. И да, они имеют значения, отличные от ascii.

2. Итак, как на самом деле выглядят строки? Если это строки, понятные человеку, расшифруйте их с помощью правильной кодировки. Если нет, то используйте base64 .

3. Создать файл и прочитать из него? Сложное решение простой проблемы. Извините, -1.

4. (И использование ascii ограничено без причины, вместо этого используйте latin1).

5. @LennartRegebro: Это не сработало бы в Python 2; попробуйте 'xff'.encode('latin1') .

Ответ №3:

Вы могли бы хранить данные в кодировке base64.

Первым шагом будет преобразование в base64:

 >>> import base64
>>> base64.b64encode(b"x80xFF")
b'gP8='
  

Это должно быть сделано один раз, и использование b или нет зависит от версии Python, которую вы используете для этого.

На втором шаге вы помещаете эту байтовую строку в программу без b . Тогда гарантируется, что она работает в py2 и py3.

 import base64
x = 'gP8='
base64.b64decode(x.encode("latin1"))
  

дает вам a str 'x80xff' в 2.6 (также должно работать в 2.5) и a b'x80xff' в 3.x.

В качестве альтернативы двум шагам, описанным выше, вы можете сделать то же самое с шестнадцатеричными данными, вы можете сделать

 import binascii
x = '80FF'
binascii.unhexlify(x) # `bytes()` in 3.x, `str()` in 2.x
  

Комментарии:

1. Упс, код будет довольно загадочным. Не можем ли мы найти решение, которое будет работать с hex.

2. Вы пробовали код на Python3? binascii.unhexlify(x) дает TypeError: 'str' does not support the buffer interface

3. Я не понимаю, что должна делать часть base64. Вы можете удалить ее, и она все равно будет работать.

4. @sorin: странно… здесь он отлично работает Python 3.1 (r31:73572, Jul 5 2010, 13:15:03) . Возможно x.encode("latin1") , здесь тоже работает лучше…

5. @Lennart Regebro Предполагается, что это альтернатива, поскольку предпочтительнее использовать hex. b'x80xff' кодируется 'gP8=' в base64 и '80FF' в hex.