[python] 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) 

위의 파이썬 코드는 다음과 같은 오류를 발생시킵니다.

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를 사용하는 경우 stringPython 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 편집

예, 비 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. 이로 인해 파이썬은 파일을 바이너리가 아닌 텍스트 파일로 엽니 다. 그러면 모든 것이 잘 작동합니다.

완전한 프로그램은 다음과 같습니다.

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 선언 은 문자열로 전달 된 것처럼 보입니다 file.write(str). 실제로 바이트 배열을 전달할 때 다음과 같은 선언을 읽었을 것 file.write(bytes)입니다. 당신은 문제가 간단하게 다음과 같이 읽을 경우, file.write(bytes)A가 필요 바이트 얻을 종류와 py3에를 바이트를 밖으로의 str을 당신이 그것을 변환 :

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

py2 docs가 왜 file.write문자열을 사용 한다고 선언 했습니까? py2에서 선언 구별은 중요하지 않았습니다.

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

py2 의 str-bytes 클래스에는 어떤 방법으로 문자열 클래스처럼 작동하고 다른 방법으로 바이트 배열 클래스처럼 동작하도록하는 메소드 / 생성자가 있습니다. 편리 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에서 문자열 의 len 을 요구한다고 생각 하고 인코딩에서 바이트 배열의 길이를 얻었습니다. 그 모호성은 이중 의무 수업의 근본적인 문제입니다. 어떤 버전의 메소드 호출을 구현합니까?

좋은 소식은 py3 이이 문제를 해결한다는 것입니다. strbytes 클래스를 분리합니다 . 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’문자를 제거하는 경우에 유용합니다. 누군가 더 나은 아이디어를 얻었 으면 언제든지 제안하거나 언제든지 편집 할 수 있습니다. 나는 초보자입니다.


답변

의 경우 Djangodjango.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'))
    ...