[Python] 인코딩 오류 없이 텍스트 파일 읽기


def read_file(path):
  f = open(path, "r")
  line = f.readline()

  data = ""
  while line:
    data += line
    line = f.readline()
    f.close()
  return data

smi 자막 파일을 열어서 싱크 조절을 위해 다음과 같이 코딩하고 즐거운 마음으로 실행을 하였습니다.

 

 

 

 

 

 

 

 

 

 

 

 

UnicodeDecodeError: 'cp949' codec can't decode byte 0x01 in position 1: illegal multibyte sequence

 

어김없이 등장하는 오류.. 인터넷에 검색해보니 수많은 예제가 뜨네요.

 

인코딩이 안 맞아서 안 열리나 봅니다. 파이썬은 기본적으로 파일이 ANSI로 작성되었다고 가정하고 cp949라는 코덱으로 파일을 엽니다.

 

open('파일경로', 'rt', encoding='UTF8')

'or'

open('파일경로', 'r', encoding='UTF8')

인터넷을 보니 이렇게 매개변수 옵션으로 UTF8을 주면 된다고 하네요

 

 

 

 

 

 

 

'utf-8' codec can't decode byte 0xff in position 0: invalid start byte

뭐야.. 안되잖아 ?? 

 

확인해보니 파일 인코딩이 UTF-16입니다. UTF-16으로 바꿔서 열어보니 잘 열리네요.

인터넷에선 일반적으로 cp949로 안 열리면 utf8로 대부분 해결이 됐기 때문에 별다른 방법이 나와있진 않은 거 같네요.

 

파일 별로 인코딩이 다 다른경우가 있을 텐데 어떻게 해결할지 생각을 조금 해보았습니다.

 

try:
	f = open(path, "r", 'utf-8')
	lines = f.readlines()
except:
	try:
		f = open(path, "r", 'utf-16')
		lines = f.readlines()
	except:
		print("Error")

처음에 생각한 방법은 예외처리를 이용하는 방법입니다.

try로 실행하고 예외 발생시 다른 인코딩으로 여는 방법입니다.

 

근데 이건 좀 문제인게 인코딩이 수십 가지가 넘을 건데 이렇게 쓰면 try except가 겹겹이 반복되어서 코드도 지저분하고 별로입니다. 도저히 마음에 드는 방법이 아니네요.

 

함수로 만들어서 재귀호출 하는 방법도 생각해봤는데 이것도 제 마음엔 들지 않았습니다.

 

혹시 파일을 열었을때 인코딩을 자동으로 인식하는 방법이 있지 않을까? 해서 찾아보니 관련 라이브러리를 찾았습니다.

 

소스코드

 

chardet이라는 모듈이 그 역할을 합니다. 

 

pip install chardet

위 명령어를 통해 chardet을 미리 설치해주세요.

 

import os
import chardet

def read_file(path):
    
    #파일 열어서 인코딩 확인
    rawdata = open(path, 'rb').read()
    result = chardet.detect(rawdata)
    enc = result['encoding']
    
    #인코딩 맞게 열기
    f = open(path, "r", encoding = enc)
    line = f.readline()

    data = ""
    while line:
        data += line
        line = f.readline()
    f.close()
    return data

 

위와 같이 일단 한번 읽어서 인코딩을 확인하고 그 인코딩 값을 open 함수에 넘겨서 한번 더 읽습니다.

두 번 읽는다는 점에선 효율성이 좀 떨어지면 예외처리로 하는 방법보단 훨~씬 나아서 공유합니다.

 

물론 chardet이 모든 인코딩을 인식하진 않으므로 특정 인코딩에선 못 읽을 수 있으나 웬만하면 다 된다고 보시면 됩니다. 아랍어 같은 거 쓰지 않는 이상요 ^^;;

 

그리고 chardet에서 반환한 인코딩 값이 open 함수에서 받는 encoding 매개변수랑 좀 다를 수 있습니다.

ex) chardet output : euc-kr -> open input : euckr :: not fit

아직까지 이런 문제는 확인을 못해봤으나 이런 문제가 발생한다면 따로 예외처리가 필요해보입니다.

 

 

이제 어떤 파일을 읽던 잘 읽습니다. UTF8이던 , UTF16이던, ANSI이던..

 

그나저나 정규식 쓰는게 너무 어렵네요 ㅠ 특정 텍스트 위치부터 싱크 조절하는 프로그램이 필요한데 마땅하게 쓸만한 라이브러리도 없어서 직접만들고 있습니다

COMMENT WRITE