plaintext = input("Please enter the text you want to compress")
filename = input("Please enter the desired filename")
with gzip.open(filename + ".gz", "wb") as outfile:
outfile.write(plaintext)
上面的python代码给我以下错误:
Traceback (most recent call last):
File "C:/Users/Ankur Gupta/Desktop/Python_works/gzip_work1.py", line 33, in <module>
compress_string()
File "C:/Users/Ankur Gupta/Desktop/Python_works/gzip_work1.py", line 15, in compress_string
outfile.write(plaintext)
File "C:\Python32\lib\gzip.py", line 312, in write
self.crc = zlib.crc32(data, self.crc) & 0xffffffff
TypeError: 'str' does not support the buffer interface
#1 楼
如果使用Python3x,则string
与Python 2.x的类型不同,必须将其强制转换为字节(对其进行编码)。plaintext = input("Please enter the text you want to compress")
filename = input("Please enter the desired filename")
with gzip.open(filename + ".gz", "wb") as outfile:
outfile.write(bytes(plaintext, 'UTF-8'))
也不要使用变量名,例如
string
或file
,而它们是模块或函数的名称。@Tom
我使用UTF-8编码的波兰字母:
plaintext = 'Polish text: ąćęłńóśźżĄĆĘŁŃÓŚŹŻ'
filename = 'foo.gz'
with gzip.open(filename, 'wb') as outfile:
outfile.write(bytes(plaintext, 'UTF-8'))
with gzip.open(filename, 'r') as infile:
outfile_content = infile.read().decode('UTF-8')
print(outfile_content)
评论
奇怪的是,它修复了它。原始代码在3.1下为我工作,文档中的示例代码也未明确编码。如果在非ASCII文本上使用它,gunzip是否可以将其解压缩?我有一个错误。
–汤姆·齐奇(Tom Zych)
2011年3月29日在10:59
我在Unicode印地语中输入了我的姓名,并成功将其压缩到gzip中。我正在使用Python 3.2
–未来之王
11年3月29日在11:15
@Tom Zych:可能与3.2中的更改有关:docs.python.org/dev/whatsnew/3.2.html#gzip-and-zipfile
– Skurmedel
11年3月29日在11:15
我使用ActiveState Python 3.1和3.2对其进行了测试。在我的机器上,两者均可工作。
–MichałNiklas
2011年3月29日在11:21
对于文件压缩,您应该始终以二进制模式打开输入:您需要稍后能够解压缩文件并获得完全相同的内容。不需要先转换为Unicode(str),也可以转换为Unicode(str),并冒着解码错误或输入与输出之间不匹配的风险。
–alexis
16-10-17在11:46
#2 楼
有一个更简单的解决方案。这将导致Python以文本文件而不是二进制文件的形式打开文件。然后一切都将正常工作。完整的程序变成这样:
评论
它也可以在python2上工作吗?可能是使代码在python2和python3上工作的一种方法吗?
–LoïcFaure-Lacroix
2015年10月6日在16:38
哇,伙计,你很好!谢谢!让我投票给你。这应该是公认的答案:))
–Loïc
15年11月27日在21:57
添加“ t”可能会产生副作用。在Windows上,编码为文本的文件会将换行符(“ \ n”)转换为CRLF(“ \ r \ n”)。
– BitwiseMan
16年1月19日在20:08
#3 楼
您不能将Python 3的“字符串”序列化为字节,而无需将其显式转换为某种编码。 br />可能就是您想要的。同样适用于python 2.x和3.x。#4 楼
对于Python 3.x,您可以通过以下方式将文本转换为原始字节:bytes("my data", "encoding")
例如:
bytes("attack at dawn", "utf-8")
返回的对象将与
outfile.write
一起使用。#5 楼
从py2切换到py3时,通常会出现此问题。在py2中,plaintext
既是字符串,也是字节数组类型。在py3中,plaintext
只是一个字符串,当以二进制模式打开outfile.write()
时,方法outfile
实际上采用字节数组,因此引发了异常。将输入更改为plaintext.encode('utf-8')
以解决问题。继续阅读,如果这困扰您。 在py2中,file.write的声明使您好像传入了一个字符串:
file.write(str)
。实际上,您正在传递一个字节数组,您应该已经读过这样的声明:file.write(bytes)
。如果您这样阅读,问题很简单,file.write(bytes)
需要一个字节类型,并且在py3中要从str中获取字节,就可以将其转换: py2 docs file.write
声明了字符串?在py2中,声明的区别并不重要,因为:方式和其他类型的字节数组类。方便file.write
吗?:py3>> outfile.write(plaintext.encode('utf-8'))
为什么py3破坏了这个不错的系统?好吧,因为在py2中,基本字符串函数不适用于世界其他地方。测量带有非ASCII字符的单词的长度吗?编码中字节数组的长度。这种含糊不清是双重责任阶层的根本问题。您实现哪种方法调用版本?
那么好消息是py3可以解决此问题。它解开了str和bytes类。 str类具有类似于字符串的方法,单独的byte类具有字节数组方法:
py2>> str==bytes #str and bytes aliased a single hybrid class in py2
True
希望知道这有助于消除问题的神秘性,并且使迁移困难容易承受。
#6 楼
>>> s = bytes("s","utf-8")
>>> print(s)
b's'
>>> s = s.decode("utf-8")
>>> print(s)
s
如果对删除烦人的'b'字符有用,如果对您有用,如果有人有更好的主意,请建议我或随时在这里进行编辑。我只是新手
评论
您也可以使用s.encode('utf-8')来代替s = bytes(“ s”,“ utf-8”),使之与s.decode('utf-8')一样
– Hans Zimermann
2015年8月1日21:00
#7 楼
对于Django
单元测试中的django.test.TestCase
,我更改了Python2语法:def test_view(self):
response = self.client.get(reverse('myview'))
self.assertIn(str(self.obj.id), response.content)
...
要使用Python3
.decode('utf8')
语法:def test_view(self):
response = self.client.get(reverse('myview'))
self.assertIn(str(self.obj.id), response.content.decode('utf8'))
...
评论
@MikePennington:请解释为什么压缩文本没有用?