Python 类型错误:';str';不支持缓冲区接口 plaintext=input(“请输入要压缩的文本”) filename=输入(“请输入所需的文件名”) 以gzip.open(文件名+“.gz”,“wb”)作为输出文件: outfile.write(纯文本)
上面的python代码给了我以下错误:Python 类型错误:';str';不支持缓冲区接口 plaintext=input(“请输入要压缩的文本”) filename=输入(“请输入所需的文件名”) 以gzip.open(文件名+“.gz”,“wb”)作为输出文件: outfile.write(纯文本),python,string,gzip,Python,String,Gzip,上面的python代码给了我以下错误: 回溯(最近一次呼叫最后一次): 文件“C:/Users/Ankur-Gupta/Desktop/Python_-works/gzip_-work1.py”,第33行,在 压缩字符串() 文件“C:/Users/Ankur Gupta/Desktop/Python_works/gzip_work1.py”,第15行,压缩字符串 outfile.write(纯文本) 写入文件“C:\Python32\lib\gzip.py”,第312行 self.crc=zl
回溯(最近一次呼叫最后一次):
文件“C:/Users/Ankur-Gupta/Desktop/Python_-works/gzip_-work1.py”,第33行,在
压缩字符串()
文件“C:/Users/Ankur Gupta/Desktop/Python_works/gzip_work1.py”,第15行,压缩字符串
outfile.write(纯文本)
写入文件“C:\Python32\lib\gzip.py”,第312行
self.crc=zlib.crc32(数据,self.crc)&0xffffffff
TypeError:“str”不支持缓冲区接口
如果不将Python 3“字符串”明确转换为某些编码,则无法将其序列化为字节
outfile.write(纯文本.encode('utf-8'))
这可能是你想要的。这同样适用于python 2.x和3.x。对于python 3.x,您可以通过以下方式将文本转换为原始字节:
bytes("my data", "encoding")
例如:
bytes("attack at dawn", "utf-8")
返回的对象将使用
outfile.write
如果使用Python3x,则string
与Python2.x的类型不同,必须将其强制转换为字节(编码)
当变量名是模块或函数名时,也不要使用变量名,如string
或file
编辑@Tom
是的,非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)
这个问题有一个更容易的解决办法 您只需在模式中添加一个
t
,使其成为wt
。这会导致Python将文件作为文本文件而不是二进制文件打开。然后一切都会好起来的
完整的程序如下所示:
plaintext=input(“请输入要压缩的文本”)
filename=输入(“请输入所需的文件名”)
以gzip.open(文件名+“.gz”,“wt”)作为输出文件:
outfile.write(纯文本)
如果有人有更好的主意,请建议我或随时在这里编辑我。我只是
Django.test.TestCase
中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'))
...
从py2切换到py3时通常会出现此问题。在py2中,明文既是字符串又是字节数组类型。在py3中,
明文
只是一个字符串,当以二进制模式打开outfile
时,方法outfile.write()
实际上采用字节数组,因此引发异常。将输入更改为plaintext.encode('utf-8')
以解决此问题。如果这困扰你,请继续阅读
在py2中,字符串使它看起来像是传入了一个字符串:file.write(str)
。实际上,您正在传入一个字节数组,您应该像这样读取声明:file.write(bytes)
。如果您这样阅读,问题很简单,file.write(bytes)
需要一个bytes类型,在py3中,要从str中获取字节,您需要转换它:
py3>> outfile.write(plaintext.encode('utf-8'))
为什么py2文档声明file.write
使用字符串?在py2中,声明的区别并不重要,因为:
py2>> str==bytes #str and bytes aliased a single hybrid class in py2
True
py2的str bytes类具有方法/构造函数,这些方法/构造函数在某些方面使其行为类似于字符串类,在另一些方面使其行为类似于字节数组类。方便文件。写不是吗
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中,基本的字符串函数不适用于世界其他地方。使用非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中字符串的len,您是在从编码中获得字节数组的长度。这种模糊性是双重责任阶级的根本问题。您实现了任何方法调用的哪个版本
好消息是py3解决了这个问题。它分离str和bytes类。str类具有类似字符串的方法,separate bytes类具有字节数组方法:
py3>> len('¡ok') #string
3
py3>> len('¡ok'.encode('utf-8')) #bytes
4
希望知道这一点有助于揭开问题的神秘面纱,让迁移的痛苦更容易承受 奇怪的是,这把它修好了;原始代码在3.1下为我工作,文档中的示例代码也没有显式编码。如果您在非ASCII文本上使用它,gunzip会解压缩它吗?我出错了。我用Unicode印地语输入了我的名字,它成功地用gzip压缩了它。我正在使用Python3。2@TomZych:可能与3.2中的更改有关:我用ActiveState Python 3.1和3.2测试了它。在我的机器上,它可以在两种模式下工作。对于文件压缩,您应该始终以二进制模式打开输入:您需要能够稍后解压缩文件并获得完全相同的内容。转换为Unicode(str
)并返回是不必要的,并且有解码错误或输入与输出不匹配的风险。您也可以使用s.encode('utf-8')
将python改为s.decode('utf-8')
,以取代s=bytes(“s”,“utf-8”)
它对python2也有效吗?这可能是一种让代码在python2和python3上运行的方法吗?哇,老兄,你真棒!谢谢让我投票支持你。这应该是公认的答案:)添加“t”可能会产生副作用。在windows上,编码为文本的文件将换行符(“\n”)转换为CRLF(“\r\n”)。@MikePennington:请解释为什么压缩文本没有用?
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
py3>> len('¡ok') #string
3
py3>> len('¡ok'.encode('utf-8')) #bytes
4