TypeError:'str'不支持缓冲区接口
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 
	
 如果使用Python3x,则string与Python 2.x的types不同,必须将其转换为字节(对其进行编码)。 
 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')) 
 也不要使用variables名称,如string或file而这些名称是模块或函数的名称。 
编辑@汤姆
是的,非ASCII文本也被压缩/解压。 我使用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) 
这个问题有一个更简单的解决scheme。
 你只需要添加一个t模式,所以它变成wt 。 这导致Python将文件作为文本文件打开,而不是二进制文件。 那么一切都将正常工作。 
完整的程序变成这样:
 plaintext = input("Please enter the text you want to compress") filename = input("Please enter the desired filename") with gzip.open(filename + ".gz", "wt") as outfile: outfile.write(plaintext) 
你不能序列化一个Python 3'string'到字节而不需要转换成某种编码。
 outfile.write(plaintext.encode('utf-8')) 
可能是你想要的。 这也适用于Python 2.x和3.x.
对于Python 3.x,您可以通过以下方式将文本转换为原始字节:
 bytes("my data", "encoding") 
例如:
 bytes("attack at dawn", "utf-8") 
 返回的对象将与outfile.write 。 
 从py2切换到py3时,通常会发生此问题。 在py2 plaintext是一个string和一个字节数组types。 在py3 plaintext中只有一个string , outfile.write()方法在outfile以二进制模式打开时实际上需要一个字节数组 ,所以会引发一个exception。 将input更改为plaintext.encode('utf-8')以解决问题。 如果这让你感到困扰,请继续阅读。 
 在py2中,file.write 声明使得它看起来像你传递了一个string: file.write(str) 。 实际上,你传递的是一个字节数组,你应该像这样读取声明: file.write(bytes) 。 如果你这样读,问题很简单, file.write(bytes)需要一个字节types,并且在py3中将字节从你转换的str中取出: 
 py3>> outfile.write(plaintext.encode('utf-8')) 
 为什么py2文件声明file.write带了一个string? 在py2中,声明的区别并不重要,因为: 
 py2>> str==bytes #str and bytes aliased a single hybrid class in py2 True 
  py2的str-bytes类有一些方法/构造函数,它们在某些方面performance得像一个string类,而在另一些方面则是一个字节数组类。 方便file.write不是吗?: 
 py2>> plaintext='my string literal' py2>> type(plaintext) str #is it a string or is it a byte array? it's both! py2>> outfile.write(plaintext) #can use plaintext as a byte array 
py3为什么打破这个好系统? 那么因为在py2中,基本的string函数并不适用于世界其他地方。 衡量一个非ASCII字符的单词的长度?
 py2>> len('¡no') #length of string=3, length of UTF-8 byte array=4, since with variable len encoding the non-ASCII chars = 2-6 bytes 4 #always gives bytes.len not str.len 
所有这一次,你认为你是在py2中要求一个string的len ,你从编码中获得字节数组的长度。 这个含糊不清的问题是双职class的根本问题。 您实施哪个版本的方法调用?
好消息是py3修复了这个问题。 它解开了str和字节类。 str类具有类似string的方法,单独的bytes类具有字节数组方法:
 py3>> len('¡ok') #string 3 py3>> len('¡ok'.encode('utf-8')) #bytes 4 
希望知道这有助于使这个问题变得神秘化,并使迁徙的痛苦变得容易一些。
 >>> s = bytes("s","utf-8") >>> print(s) b's' >>> s = s.decode("utf-8") >>> print(s) s 
好吧,如果有用的情况下去除烦人的'b'字符。如果任何人有更好的主意,请build议我或随时编辑我在这里任何时间。我只是新手
 对于django.test.TestCaseunit testing中的Django ,我改变了我的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')) ...