распаковка bz2 с помощью Python 3.4 - TypeError: 'str' не поддерживает интерфейс буфера

Есть похожие ошибки, но решения для bz2 я не нашел.

Следующая программа не работает при распаковке:

import bz2

un =  'BZh91AY&SYA\xaf\x82\r\x00\x00\x01\x01\x80\x02\xc0\x02\x00 \x00!\x9ah3M\x07<]\xc9\x14\xe1BA\x06\xbe\x084'
pw =  'BZh91AY&SY\x94$|\x0e\x00\x00\x00\x81\x00\x03$ \x00!\x9ah3M\x13<]\xc9\x14\xe1BBP\x91\xf08'
decoded_un = bz2.decompress(un)
decoded_pw = bz2.decompress(pw)

print(decoded_un)
print(decoded_pw)

Я пытался использовать bytes(un, 'UTF-8), но это не сработало. Я думаю, что у меня не было этой проблемы в Python 3.3.

РЕДАКТИРОВАТЬ: это было для задачи Python. У меня есть два бита кода, которые работают благодаря Мартейну:

import bz2

un_saved =  'BZh91AY&SYA\xaf\x82\r\x00\x00\x01\x01\x80\x02\xc0\x02\x00 \x00!\x9ah3M\x07<]\xc9\x14\xe1BA\x06\xbe\x084'
pw_saved =  'BZh91AY&SY\x94$|\x0e\x00\x00\x00\x81\x00\x03$ \x00!\x9ah3M\x13<]\xc9\x14\xe1BBP\x91\xf08'
print(bz2.decompress(un_saved.encode('latin1')))
print(bz2.decompress(pw_saved.encode('latin1')))

Этот работает с веб-страницы:

# http://www.pythonchallenge.com/pc/def/integrity.html

import urllib.request
import re
import os.path
import bz2

fname = "008.html"

if not os.path.isfile(fname):
    url = 'http://www.pythonchallenge.com/pc/def/integrity.html'
    response = urllib.request.urlopen(url)
    webpage = response.read().decode("utf-8")
    with open(fname, "w") as fh:
        fh.write(webpage)

with open(fname, "r") as fh:
    webpage = fh.read()
    re_un = '\\nun: \'(.*)\'\\n'
    m = re.search(re_un, webpage)
    un = m.group(1)
    print(un)

    pw_un = '\\npw: \'(.*)\'\\n'
    m = re.search(pw_un, webpage)
    pw = m.group(1)
    print(pw)

    unde = un.encode('latin-1').decode('unicode_escape').encode('latin1')
    pwde = pw.encode('latin-1').decode('unicode_escape').encode('latin1')
    decoded_un = bz2.decompress(unde)
    decoded_pw = bz2.decompress(pwde)

    print(decoded_un)
    print(decoded_pw)

person BlueTrin    schedule 24.12.2014    source источник


Ответы (1)


Библиотека bz2 работает с bytes объектами, а не со строками:

un = b'BZh91AY&SYA\xaf\x82\r\x00\x00\x01\x01\x80\x02\xc0\x02\x00 \x00!\x9ah3M\x07<]\xc9\x14\xe1BA\x06\xbe\x084'
pw = b'BZh91AY&SY\x94$|\x0e\x00\x00\x00\x81\x00\x03$ \x00!\x9ah3M\x13<]\xc9\x14\xe1BBP\x91\xf08'

Другими словами, использование bytes() прекрасно работает, просто убедитесь, что вы используете правильную кодировку. UTF-8 — это не та кодировка; если у вас есть маскировка байтов как кодовые точки строковых символов, вместо этого используйте Latin-1 для кодирования; Latin 1 отображает символы один на один в байты:

un = un.encode('latin1')

or

un = bytes(un, 'latin1')

Также см. Python Unicode HOWTO:

Latin-1, также известная как ISO-8859-1, представляет собой аналогичную кодировку. Кодовые точки Unicode 0–255 идентичны значениям Latin-1, поэтому преобразование в эту кодировку просто требует преобразования кодовых точек в байтовые значения; если встречается кодовая точка больше 255, строка не может быть закодирована в Latin-1.

Я оставлю расшифровку вам. Получайте удовольствие от Python Challenge!

Обратите внимание: если вы загрузили эти символы как есть с веб-страницы, они будут не готовыми байтами! У вас будут символы '\', 'x', 8 и 2, а не кодовая точка с шестнадцатеричным значением 82. Сначала вам нужно будет интерпретировать эти последовательности как строковый литерал Python:

>>> un = r'BZh91AY&SYA\xaf\x82\r\x00\x00\x01\x01\x80\x02\xc0\x02\x00 \x00!\x9ah3M\x07<]\xc9\x14\xe1BA\x06\xbe\x084'
>>> un
'BZh91AY&SYA\\xaf\\x82\\r\\x00\\x00\\x01\\x01\\x80\\x02\\xc0\\x02\\x00 \\x00!\\x9ah3M\\x07<]\\xc9\\x14\\xe1BA\\x06\\xbe\\x084'
>>> un.encode('latin-1').decode('unicode_escape')
'BZh91AY&SYA¯\x82\r\x00\x00\x01\x01\x80\x02À\x02\x00 \x00!\x9ah3M\x07<]É\x14áBA\x06¾\x084'
>>> un.encode('latin-1').decode('unicode_escape').encode('latin1')
b'BZh91AY&SYA\xaf\x82\r\x00\x00\x01\x01\x80\x02\xc0\x02\x00 \x00!\x9ah3M\x07<]\xc9\x14\xe1BA\x06\xbe\x084'

Обратите внимание на двойную обратную косую черту в представлении un. Только последний результат bytes может быть распакован!

person Martijn Pieters    schedule 24.12.2014
comment
У вас есть ссылка, которую я мог бы использовать, чтобы понять другую кодировку? Я действительно борюсь с этим... Это было для Python Challenge... - person BlueTrin; 25.12.2014
comment
@BlueTrin: да, я узнал строки. Не уверен, что у меня есть для вас ссылка, но имейте в виду, что задача была написана для Python 2 до того, как Python 3 стал мейнстримом. - person Martijn Pieters; 25.12.2014
comment
joelonsoftware.com/articles/Unicode.html farmdev.com/talks/unicode - person Ignacio Vazquez-Abrams; 25.12.2014
comment
@IgnacioVazquez-Abrams: менее полезен в этом контексте, когда байты берутся с веб-страницы, но любой метод извлечения, используемый OP, дает им строку, а не байты. - person Martijn Pieters; 25.12.2014
comment
@BlueTrin: я подозреваю, что здесь что-то еще не так, я обновил ответ. Можете ли вы в будущем убедиться, что вы всегда включаете полную ошибку, которую вы получили, с кодом, который вы пробовали? - person Martijn Pieters; 25.12.2014
comment
Я пытался понять сам, как решить чтение с веб-страницы. В итоге я написал то же самое, что и в вашем решении. - person BlueTrin; 25.12.2014