bz2用Python 3.4解压缩 - TypeError:' str'不支持缓冲区接口

时间:2014-12-24 21:09:52

标签: python python-3.4 bzip2

有类似的错误,但我找不到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的挑战我有两位代码,感谢Martijn:

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)

1 个答案:

答案 0 :(得分: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')

un = bytes(un, 'latin1')

另见Python Unicode HOWTO

  

Latin-1,也称为ISO-8859-1,是一种类似的编码。 Unicode代码点0-255与Latin-1值相同,因此转换为此编码只需要将代码点转换为字节值;如果遇到大于255的代码点,则该字符串不能编码为Latin-1。

我会把解码留给你。享受Python挑战吧!

请注意,如果您从网页加载 这些字符,那么它们将由现成的字节组成!您将拥有字符'\''x'82,而不是具有十六进制值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表示中的 double 反斜杠。只有最后bytes个结果才可解压缩!