programing

Python 3에서 파일 내용을 처리할 때 "TypeError: "str"이 아닌 바이트와 유사한 개체가 필요합니다."

css3 2023. 4. 15. 09:10

Python 3에서 파일 내용을 처리할 때 "TypeError: "str"이 아닌 바이트와 유사한 개체가 필요합니다."

최근에 Python 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에서는 '3.5if 'some-pattern' in tmp: continue 에러가 됩니다.「 ,, 음, 음, 다, 다, 다, 다, 다, 다 line line.

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

는 이 하지 못했다..decode()in, 나는, i, 용, 를, 를, 를, 습을 사용해서도 고칠 수 없었다

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

무엇이 문제이며 어떻게 수정해야 합니까?

파일을 바이너리 모드로 열었습니다.

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

, 가 ,, 일, 일, 일, 일, 음, this, 음, 음, 음, 음, 음, this, this, this, this, this, this 으로 반환됩니다.bytes ""가 아닌 ""str 격납 에서 문자열을 할 수 그 후 격납 테스트에서 문자열을 사용할 수 없습니다.

if 'some-pattern' in tmp: continue

하면에요.bytestmp★★★★

if b'some-pattern' in tmp: continue

파일을 나 파일을 .'rb'를 지정합니다.'r'.

을 하려면 , 「」를 사용합니다..encode()

예:

'Hello World'.encode()

있듯이 바이트와 같은 오브젝트로 인코딩해야 합니다.encode()이치노

이미 언급했듯이 파일을 바이너리 모드로 읽고 바이트 목록을 만듭니다.다음 for loop에서는 문자열을 바이트와 비교하고 있으며, 여기서 코드가 실패합니다.

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

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'>

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.지원되지 않는 작업: 쓰기

encode() 함수는 단일 따옴표로 지정된 하드코드 문자열 값과 함께 사용합니다.

예:

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

또는

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

예에서는 the음음 for 、 for 、 for 、 가 、 가 、 for 、 for 、 for for 。b 전에'GET http://www.py4inf.com/code/romeo.txt HTTP/1.0\n\n'문제를 해결했습니다.

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()

문자열 리터럴 앞에서 'b'자는 무엇을 합니까?

파일을 바이너리 모드로 열었습니다.

다음 코드는 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')

파일을 텍스트로 열어 보십시오.

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

또한 공식 페이지에는 Python 3.x용 링크가 있습니다: io - 스트림 관련 작업을 위한 핵심 도구입니다.

이것이 오픈 기능입니다.오픈

정말로 바이너리로 처리하려고 하는 경우는, 문자열을 부호화하는 것을 검토해 주세요.

에러는, 문자( 문자열)를 「(열)」로 때에 했습니다.bytesPython 2.7 python음음 음음 음음 python python python python python python python

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

이것은 유니코드 문자를 다룰 때 Python 2.7의 방식이다.

3.Python 3.6에서는 동작하지 않습니다.bytes부호화에는 추가 인수가 필요하지만 부호화에 따라 다른 결과가 출력될 수 있기 때문에 이것은 조금 까다로울 수 있습니다.

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

제 경우 문제를 해결하기 위해 바이트 인코딩을 사용해야 했습니다.

요약

Python 2.x는 WRT를 사용합니다. 그 은 「」, 「」입니다.str는 실제로 표준에은 Unicode 표준입니다).unicode스트링 리터럴코드 페이지」스타일의 인코딩을 상정하지 않고, 스트링과 같이 취급하는 편리한 기능도 있습니다.

3에서는 "의해 문자열이 되어 내장 두 않게 .3 .x에서는 "string literals"에 의해 실제 문자열이 생성되어 내장 기능으로 인해 두 유형 간의 암묵적인 변환이 이루어지지 않게 되었습니다. 때문에,에 「」, 「」, 「」, 「」, 「」, 「」가 붙게 되었습니다.TypeError리터럴과 변수가 호환되지 않는 유형이기 때문입니다.이 문제를 해결하려면 몇 가지 값을 바꾸거나 변환하여 유형이 일치하도록 해야 합니다.

Python 문서에는 Unicode를 올바르게 사용하기 위한 매우 상세한 가이드가 포함되어 있습니다.

질문의 예에서는 입력 파일이 텍스트가 포함된 것처럼 처리됩니다.따라서 파일을 텍스트 모드로 열어야 합니다.2 줄바꿈3.에서는 2.x 의 줄바꿈 변환을 합니다.newline키워드 파라미터는 텍스트모드로 파일을 열 때 사용합니다.

파일을 텍스트로 올바르게 읽으려면 텍스트 인코딩을 알아야 합니다. 텍스트 인코딩은 코드에서 (문자열) 이름으로 지정됩니다.부호화iso-8859-1을 사용하다각 바이트를 개별적으로 해석하여 최초의 256 Unicode 코드 포인트 중 하나를 순서대로 나타냅니다(따라서 무효 데이터로 인한 예외는 발생하지 않습니다). utf-8그러나 경우 구별은 중요하지 않습니다ASCII의 입니다.ASCII를 사용합니다.

다음과 같이 됩니다.

with open(fname, 'r', newline='\n', encoding='iso-8859-1') as f:
    lines = [x.strip() for x in f.readlines()]

# proceed as before
# If the results are wrong, take additional steps to ascertain the correct encoding

2.x에서 3.x로 마이그레이션할 때 오류가 생성되는 방법

2 2.x의 'some-pattern' 내다str즉, 프로그래머가 텍스트로 가장할 가능성이 높은 일련의 바이트입니다.str입니다.bytes입력합니다.unicode텍스트를 올바르게 나타내는 타입.이 데이터를 텍스트인 것처럼 취급하기 위해 많은 방법이 제공되고 있지만 텍스트의 적절한 표현은 아닙니다.텍스트 문자(부호화)로서의 각 값의 의미가 상정됩니다.(원데이터를 '텍스트'로 착각할 수 있도록 하기 위해, 경우에 따라서는 Raw data와 Raw data 사이에 암묵적인 변환이 있을 수 있습니다.str ★★★★★★★★★★★★★★★★★」unicode그러나, 이것은 그 자체로 혼란스러운 오류를 초래한다 - 예를 들어,UnicodeDecodeError호호화호시는는 。

3 3.x의 'some-pattern' '만들다'라고 요.str 지금은str유니코드】(유니코드】【유니코드】(【유니코드unicode되지 않게 , 「」만 사용됩니다.bytes을 이용하다 가지 변경 사항이 있습니다.bytes(해서) bytes오브젝트는 이제 결과입니다.int 1이 )bytes 기묘한 되지 않는 방식 은 그대로 유지됩니다.예를 들어, 「 문자열에서도 거의 되지 않는 」입니다.zfill를 참조해 주세요.

이것이 문제의 원인

자료, 자료, 자료,tmp는 입니다.bytes사례.바이너리 소스로부터 온 것입니다.이 경우, 파일은'b' 「 」의 경우는, 「 」, 」(Web 「」)로 작성된 소켓으로부터 .urllibAPI를 사용합니다.

, 문자열과 조합하여 의미 있는 작업을 수행할 수 없습니다.문자열의 요소는 유니코드 코드 포인트(대부분 텍스트 문자를 나타내는 추상화, 모든 세계 언어 및 기타 많은 기호를 나타내는 범용 형식)입니다.의 요소bytes(구체적으로3.x에서는~255 범위해석됩니다.)

때, 문자 의 「」는 「」로 되어 있습니다.'some-pattern'에서 출발하다bytes이치노따라서 코드는 합법적인 비교(바이트 시퀀스에서 바이트 시퀀스로)에서 부정한 비교(문자열에서 바이트 시퀀스로)로 넘어갔습니다.

문제의 해결

시퀀스로 - 와 여부를 합니다.== 와의 , " " " 。<를 사용한 , " " " "in와의 , 「」+, 또는 기타 - 문자열을 바이트 시퀀스로 변환하거나 그 반대로 변환해야 합니다.일반적으로 이들 하나만 정확하고 합리적인 답변이며 상황에 따라 달라집니다.

소스 수정

처음에 값 중 하나가 "잘못된" 것으로 보일 수 있습니다.예를 들어 파일을 읽는 것이 텍스트가 되는 경우 텍스트 모드로 열어야 합니다.3에서는, 부호화는 3.x 로서 할 수 .encoding에서 ""로openUnicode 로의 변환은, 바이너리 파일을 명시적인 번역 스텝에 입력할 필요 없이 심리스하게 처리됩니다(따라서, 범용의 줄바꿈 처리가 심리스하게 행해집니다).

원래의 예에서는, 다음과 같이 됩니다.

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

에서는 플랫폼에 의존한 파일의 디폴트 부호화를 전제로 하고 있습니다.이것은 일반적으로 동일한 컴퓨터에서 간단한 방법으로 작성된 파일에 대해 작동합니다.단, 일반적인 경우 데이터를 올바르게 사용하려면 데이터의 인코딩을 알고 있어야 합니다.

부호화가 예를 들어 UTF-8로 알려져 있는 경우, 다음과 같이 기술되어 있습니다.

with open(fname, 'r', encoding='utf-8') as f:
    lines = [x.strip() for x in f.readlines()]

마찬가지로 바이트 리터럴이어야 할 문자열 리터럴에는 단순히 프리픽스가 누락되어 있습니다.바이트 시퀀스가 정수값을 나타내도록 합니다.[101, 120, 97, 109, 112, 108, 101](즉, 문자의 ASCII 값)example 바이트 리터럴을 .b'example''이변'은 '이변'입니다.그 반대도 마찬가지입니다.

원래의 예에서는, 다음과 같이 됩니다.

if b'some-pattern' in tmp:

구문은만 허용하기 에 "bytes.bytes"와 사용할 수 있습니다.b'ëxãmþlê'로서 잡힐 것이다.SyntaxError소스 파일의 부호화에 관계없이(어떤 바이트 값이 의미하는지 명확하지 않기 때문에, 이전의 암묵적 부호화 방식에서는 ASCII 범위가 올바르게 확립되어 있었지만, 그 외의 모든 것은 공중에 있었습니다). ★★★★★★★★★★★★★★★★★.bytes을 128 255 255를 사용합니다.\x: escaping escaping 、 음 、 음 、 음 、 escaping 、 escaping 、 escaping 、 escaping 、 escaping 、 escaping escaping escaping escaping escaping escaping 。b'\xebx\xe3m\xfel\xea' 텍스트에 됩니다.ëxãmþlê(ISO 8859-1).

변환(해당하는 경우)

바이트 시퀀스와 텍스트 간의 변환은 인코딩이 결정된 경우에만 가능합니다.지금까지는 항상 그랬습니다.그냥 로컬로 인코딩을 상정하고 있었는데, 그 후로는 거의 무시해 버렸습니다.(동아시아 등지의 프로그래머들은 256개 이상의 다른 기호를 가진 스크립트를 사용할 필요가 있기 때문에, 그 텍스트는 멀티바이트 인코딩을 필요로 하기 때문에, 지금까지 이 문제를 보다 잘 인식하고 있었습니다.)

3에서는 바이트 인코딩을 할 수 이 없기 에 백그라운드에서인 변환 .3 .x에서는 바이트 시퀀스를 가정된 인코딩을 가진 텍스트로 암묵적으로 처리할 수 있어야 한다는 압박이 없기 때문에 암묵적인 변환 스텝은 없습니다., API를 하는 것은 를 、 를 、 API 이 、 를 、 this this this this this this this 。바이트는 원시 데이터이므로 추상화인 텍스트를 인코딩하는 데 사용됩니다. 때문에 '이러한'은.encode()메서드는 에 의해 제공됩니다.str(텍스트를 나타냄), 텍스트를 원시 데이터로 인코딩합니다. 「」는.decode()메서드는 에 의해 제공됩니다.bytes(바이트 시퀀스를 나타냄), 원시 데이터를 텍스트로 디코딩합니다.

UTF-8 인코딩이 적절하다고 가정했을 경우, 이것들을 샘플코드에 적용하면, 다음과 같은 결과가 됩니다.

if 'some-pattern'.encode('utf-8') in tmp:

그리고.

if 'some-pattern' in tmp.decode('utf-8'):

언급URL : https://stackoverflow.com/questions/33054527/typeerror-a-bytes-like-object-is-required-not-str-when-handling-file-conte