TypeError : Python3에서 파일에 쓸 때 'str'이 아닌 바이트와 같은 객체가 필요합니다.


590

최근에 Py 3.5로 마이그레이션했습니다. 이 코드는 Python 2.7에서 제대로 작동했습니다.

with open(fname, 'rb') as f:
    lines = [x.strip() for x in f.readlines()]

for line in lines:
    tmp = line.strip().lower()
    if 'some-pattern' in tmp: continue
    # ... code

3.5로 업그레이드하면 다음과 같은 결과가 나타납니다.

TypeError: a bytes-like object is required, not 'str'

마지막 줄에 오류가 있습니다 (패턴 검색 코드).

.decode()명령문의 양쪽 에서 함수를 사용해 보았습니다.

if tmp.find('some-pattern') != -1: continue

-소용이 없습니다.

거의 모든 2 : 3 문제를 신속하게 해결할 수 있었지만이 작은 진술로 인해 문제가 발생했습니다.


11
왜 바이너리 모드에서 파일을 열지 만 텍스트로 취급합니까?
Martijn Pieters

4
@MartijnPieters 파일 열기 모드를 찾아 주셔서 감사합니다! 텍스트 모드로 변경하면 문제가 해결되었습니다 ... 코드는 Py2k에서 수년 동안 안정적으로 작동했습니다 ...
masroore


10
요청이있는 곳 에서도이 문제가 발생하여 result = requests.get시도합니다 x = result.content.split("\n"). result.content문자열 임을 암시 .split()하고 바이트와 같은 객체가 필요 하기 때문에 오류 메시지에 약간 혼란 스럽습니다 .. ?? ( " 'str"'이 아닌 바이트와 같은 객체가 필요합니다.).

답변:


553

이진 모드에서 파일을 열었습니다.

with open(fname, 'rb') as f:

이는 파일에서 읽은 모든 데이터가 bytes아닌 객체 로 반환됨을 의미합니다 str. 그런 다음 포함 테스트에서 문자열을 사용할 수 없습니다.

if 'some-pattern' in tmp: continue

대신 bytes테스트 하기 위해 객체 를 사용해야합니다 tmp.

if b'some-pattern' in tmp: continue

또는 대신 'rb'모드를 으로 바꾸어 파일을 텍스트 파일로여십시오 'r'.


12
ppl이 링크 한 다양한 문서를 살펴보면 Py3에서는 기본 문자열이 바이트 인 반면 Py3에서는 기본 문자열이 유니 코드이므로 Py2에서 모든 것이 "작동"했음을 알 수 있습니다. 즉, I / O를 수행 할 때마다 esp. 네트워킹에서는 바이트 문자열이 표준이므로 흑백 유니 코드 및 바이트 문자열 (en / decode)을 이동하는 방법을 배워야합니다. 파일의 경우 이제 차별화를 돕기 위해 "r"대 "rb"(및 'w'& 'a')가 있습니다.
wescpy

3
@wescpy : 파이썬 2가 'r''rb' 너무 합니다 (EOF 마커 처리 방법, 번역 줄 바꿈과 같은 특정 플랫폼), 바이너리와 텍스트 파일 행동 사이의 전환. 그건 io(파이썬 2의 기본 I / O 파이썬 3의 기능 또한 사용할 수를 제공) 라이브러리는 현재 도 디코딩 기본적으로 텍스트 파일을 실제 변화이다.
Martijn Pieters

2
@MartijnPieters : 그렇습니다. 2.x에서는 'b'DOS / Windows에서 이진 파일로 작업해야 할 때만 플래그를 사용했습니다 (2 진이 POSIX 기본값이므로). io파일 액세스를 위해 3.x에서 사용할 때는 이중 목적이있는 것이 좋습니다 .
wescpy

208

다음을 사용하여 문자열을 인코딩 할 수 있습니다 .encode()

예:

'Hello World'.encode()

48

이미 언급했듯이 이진 모드에서 파일을 읽은 다음 바이트 목록을 만듭니다. 다음 for 루프에서 문자열을 바이트와 비교하고 코드가 실패하는 곳입니다.

목록에 추가하는 동안 바이트를 디코딩하면 작동합니다. 변경된 코드는 다음과 같아야합니다.

with open(fname, 'rb') as f:
    lines = [x.decode('utf8').strip() for x in f.readlines()]

바이트 유형은 Python 3에서 도입되었으며 코드가 Python 2에서 작동하는 이유입니다. Python 2에는 바이트에 대한 데이터 유형이 없었습니다.

>>> s=bytes('hello')
>>> type(s)
<type 'str'>

25

wb에서 w로 변경해야합니다.

def __init__(self):
    self.myCsv = csv.writer(open('Item.csv', 'wb')) 
    self.myCsv.writerow(['title', 'link'])

def __init__(self):
    self.myCsv = csv.writer(open('Item.csv', 'w'))
    self.myCsv.writerow(['title', 'link'])

이것을 변경하면 오류가 사라지지만 파일에는 쓸 수 없습니다 (필자의 경우). 결국 대답이 없습니까?

출처 : ^ M을 제거하는 방법

'rb'로 변경하면 다른 오류가 발생합니다. io.UnsupportedOperation : write


15

이 작은 예제의 경우 : import socket

mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect(('www.py4inf.com', 80))
mysock.send(**b**'GET http://www.py4inf.com/code/romeo.txt HTTP/1.0\n\n')

while True:
    data = mysock.recv(512)
    if ( len(data) < 1 ) :
        break
    print (data);

mysock.close()

'GET http://www.py4inf.com/code/romeo.txt HTTP / 1.0 \ n \ n' 앞에 "b"를 추가하면 문제가 해결되었습니다.


11

작은 따옴표로 묶은 하드 코딩 된 문자열 값과 함께 encode () 함수를 사용하십시오.

전의:

file.write(answers[i] + '\n'.encode())

또는

line.split(' +++$+++ '.encode())

8

이진 모드에서 파일을 열었습니다.

다음 코드는 TypeError를 발생시킵니다. 'str'이 아닌 바이트와 유사한 객체가 필요합니다.

for line in lines:
    print(type(line))# <class 'bytes'>
    if 'substring' in line:
       print('success')

다음 코드가 작동합니다. 당신은 decode () 함수를 사용해야합니다 :

for line in lines:
    line = line.decode()
    print(type(line))# <class 'str'>
    if 'substring' in line:
       print('success')


1

char (또는 string)을로 변환하려고 할 때이 오류가 발생 bytes했습니다. 파이썬 2.7에서 코드는 다음과 같습니다.

# -*- coding: utf-8 -*-
print( bytes('ò') )

이것이 파이썬 2.7 의 방법입니다 유니 코드 문자를 처리 할 때 .

bytes인코딩에 추가 인수가 필요하기 때문에 Python 3.6에서는 작동하지 않지만 다른 인코딩은 다른 결과를 출력 할 수 있으므로 약간 까다로울 수 있습니다.

print( bytes('ò', 'iso_8859_1') ) # prints: b'\xf2'
print( bytes('ò', 'utf-8') ) # prints: b'\xc3\xb2'

내 경우에는 사용해야했다 iso_8859_1 에는 문제를 해결하기 위해 바이트를 인코딩 할 때 했습니다.

이것이 누군가를 돕기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.