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:Python32libgzip.py", line 312, in write
self.crc = zlib.crc32(data, self.crc) & 0xffffffff
TypeError: 'str' does not support the buffer interface
595   7  

7 ответов:

если вы используете 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 в то время как это имена модуля или функции.

EDIT @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("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 как строка и массив байт тип. В py3 plaintext только строка, и метод outfile.write() на самом деле принимает массив байт, когда outfile открывается в двоичном режиме, поэтому возникает исключение. Измените вход на plaintext.encode('utf-8') чтобы устранить проблему. Читайте дальше, если это вас беспокоит.

в py2, в декларации для файл.пиши казалось, что вы передали в строке:file.write(str). На самом деле вы передавали в массив байтов, вы должны были читать объявление следующим образом: file.write(bytes). Если Вы читаете это так проблема проста,file.write(bytes) нужен байт тип и в py3, чтобы получить байт С str вы преобразовать его:

py3>> outfile.write(plaintext.encode('utf-8'))

почему документы py2 объявили строку? Ну в py2 декларации различия не было дело в том, что:

py2>> str==bytes         #str and bytes aliased a single hybrid class in py2
True

The str-байт класс py2 имеет методы / конструкторы, которые заставляют его вести себя как класс 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 основные строковые функции не работали для остального мира. Измерьте длину слова с символом, отличным от 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, вы получали длину массива байтов из кодировки. Эта двусмысленность является фундаментальной проблемой для классов двойного назначения. Какую версию любого вызова метода вы реализуете?

хорошая новость заключается в том, что py3 устраняет эту проблему. Он распутывает str и байт классы. Элемент str класс имеет строковые методы, отдельные байт класс имеет методы массива байтов:

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'.Если у кого-то есть лучшая идея, пожалуйста, предложите мне или не стесняйтесь редактировать меня в любое время здесь.Я просто новичок

на 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'))
    ...

Comments

    Ничего не найдено.