python에서 \ufeff가 읽힐 때 해결방법.

1 분 소요

1-line summary

  • open(file_name, "r", encoding='utf-8-sig')을 쓰면 해결 됩니다.

python에서 \ufeff가 읽히는 문제.

  • 보통 csv를 읽을 때, pandas를 쓰긴 하지만 속도 문제로 인해 csv라는 모듈을 사용할 때가 있습니다(사실 요즘은 웬만하면 pandas가 더 빠르기는 하지만요). 이 때 csv를 읽어서 dictionary로 변환하는 다음과 같은 코드를 사용할 때, 첫번째 칼럼의 key에 \ufeff가 붙는 경우가 있습니다. 즉, 첫번째 칼럼의 이름이 “Author”라면 “feffAuthor”라는 식으로 표시되는 것이죠.
with open(path+file_name, "r") as f:
    # python에서 file을 읽을 때 간혹 문자에 \ufeff 가 붙는 경우가 있음. 
    for row in csv.DictReader(f):
        row_dict = {k: row[k] for k in row.keys() if k in required_column_sets}
        row_dict_lst.append(row_dict)

일단 어떻게 해결할 수 있는가?

  • 물론 사소한 문제고 그냥 str.replace("/ufeff", "")로 처리해줘도 되는 문제이기는 합니다.
  • 다만 아래처럼 encoding='utf-8-sig'의 argument를 넘겨주는 것이 좀더 똑똑한 방법으로 보입니다.
# python에서 file을 읽을 때 간혹 문자에 \ufeff 가 붙는 경우가 있음. 
# 이 때는 encoding 방식을 변경해주면 됨 
################################################################
with open(path+file_name, "r", encoding='utf-8-sig') as f:
################################################################
    for row in csv.DictReader(f):
        row_dict = {k: row[k] for k in row.keys() if k in required_column_sets}
        row_dict_lst.append(row_dict)

Byte Order Mark: 왜 이런일이 발생했는가?

  • /ufeff는 해당 file이 어떤 문자열로 코딩되었는지를 의미하는 일종의 식별자입니다. “이 문서의 인코딩 방식은 뭐에요”라는 걸 알려주는 메타 정보인 것이죠. 보통 이러한 방식은 해당 파일의 맨 앞에 집어넣곤 합니다.
  • 다만, utf-8의 경우는 BOM이 필요없습니다. 즉 default이기 때문에, 굳이 저 정보를 집어넣을 필요가 없는데, 가끔 파일들에서 저 utf-8로 인코딩되었다는 사실을 알려주는 것이죠.
  • 따라서, utf-8-signature이라는 인코딩 방식을 넘겨주면, 앞의 정보를 무시하게 됩니다. 이는 “이 아이는 확실하게 utf-8로 인코딩된 아이야”라는 것을 정확하게 전달하는 것이죠.

wrap-up

  • 물론 그냥 pandas.read_csv를 쓰면 보통 문제없이 해결해줍니다.
  • 사람의 눈으로는 모든 것이 같은 데이터일지라도 사실은 내부의 byte 레벨에서는 다를 수 있는 것이죠.

reference

댓글남기기