UnicodeDecodeError: 'ascii' codec can't decode byte 0xec in position 0: ordinal not in range(128)
[1] 시스템 기본 인코딩 설정을 바꾸어 해결

아래의 스크립트를 Windows CMD창에서 실행하면,

# -*- coding: utf-8 -*-

if __name__ == '__main__':
    print "안녕".encode('euc-kr')

아래와 같은 오류가 생긴다.

UnicodeDecodeError: 'ascii' codec can't decode byte 0xec in position 0: ordinal not in range(128)


그런데, eclipse pydev에서 실행하면 이런 오류가 생기지 않고 잘 실행된다. 
찾아보니 아래와 같은 글이 있었다.

python 한글 문제
    http://cafecola.tistory.com/?page=8

파이썬의 기본 인코딩이 'ascii'로 설정되어 있어서 생기는 문제라고 하고,
python 설치 디렉토리 아래에 site-packages/sitecustomize.py 라는 파일을 만들고 아래와 같이 적어주면 해결된다고 하는데,

import sys
sys.setdefaultencoding("utf-8")

해보니 정말 해결되었다. 내가 쓴 버전은 CPython-2.7.1.

그리고, eclipse 설치 디렉토리를 뒤져보니 .../pydev_sitecustomize/sitecustomize.py 파일이 있고 이런 저런 조건을 살펴 default encoding을 설정하는 코드가 들어있었다. 아마 이 덕에 eclipse에서는 오류가 안 난 것 같다.

eclipse는 소스파일의 첫번째나 두번째줄에 넣는 인코딩힌트 즉, "# -*- coding: utf-8 -*-" 표시를 중요한 판단기준으로 삼는 것 같다.
  • 내장 텍스트 편집기에서 소스를 읽어들일때의 문자셋 설정에 참조할 뿐 아니라,
  • "Run As" 명령으로 소스를 실행시킬때의 기본인코딩 설정(setdefaultencoding())에도 사용한다.
    예를 들어 아래 파일을 "Run As"로 실행시키면 실행시간(run time)의 기본인코딩이 utf-8로 잡혀서 화면에도 "utf-8" 이 출력되지만, 첫 줄을 "# -*- coding: euc-kr -*-" 로 바꾸면 실행시간 기본인코딩이 euc-kr로 바뀌면서 화면에도 "euc-kr"이 출력되는 식이다. 만약 인코딩힌트를 안 주면 어떻게 될까? 그때는 eclipse의 [Window] -> [Preference] -> [General] -> [Workspace] 아래에 있는 [Text file encoding]에 설정된 기본 인코딩을 따르는 것 같다.
# -*- coding: utf-8 -*-
import sys
print sys.getdefaultencoding()



[2] 시스템 기본 인코딩 건드리지 않고 해결

그리고, 굳이 시스템 설정을 바꾸지 말고 해당 소스에서 설정할 수도 있지 않을까 해서 위 두 줄을 소스에 넣어보니, 아래와 같이 오류가 생겼다.

Traceback (most recent call last):
  File "test.py", line 13, in <module>
    sys.setdefaultencoding("utf-8")
AttributeError: 'module' object has no attribute 'setdefaultencoding'

이렇게 자기 소스 파일에 직접 넣는 대신, 작업중인 로컬 디렉토리에 앞서 썼던 sitecustomize.py를 만들어 넣고 PYTHONPATH에 로컬 디렉토리를 포함시킨 상태로 파이썬 소스를 실행하면 기본인코딩에 반영되었다 (아래 페이지 참조).

The Illusive setdefaultencoding
    http://blog.ianbicking.org/illusive-setdefaultencoding.html

c:\> set PYTHONPATH=.
c:\> python test.py


그리고, 아래 명령으로 현재의 기본인코딩을 알아낼 수 있으니 이걸로 적용여부를 확인할 수도 있다.

>>> sys.getdefaultencoding()
'utf-8'


[3] 예외 : py2exe를 쓸 때

위의 [2]에서 실패한, sys.setdefaultencoding("utf-8") 명령을 소스파일에 직접 넣는 방법이 유용한 경우도 있는데,
바로 py2exe를 이용해 배포용 실행이미지를 만들어낼 때이다.

기본인코딩을 설정하는 sitecustomize.py를 시스템 디렉토리나 로컬디렉토리에 반영하면 원본 스크립트를 python 인터프리터를 통해 직접 실행할 때는 기본인코딩이 변경되지만, 이는 스크립트를 실행할 때의 얘기일 뿐이고, py2exe를 써서 이 스크립트를 실행파일로 만들어 돌릴때는 기본인코딩이 여전히 'ascii'로 잡혀서 오류가 생긴다. 

sitecustomize.py는 아마도 현재 설치되어 동작중인 파이썬 인터프리터 환경에 영향을 주는 것으로 보이는데, py2exe가 파이썬 스크립트로부터 만들어내는 실행파일은 현재의 파이썬 환경에서의 동작을 목적으로하는 것이 아니라, 파이썬이 설치되어 있지도 않은 제3의 컴퓨터에서의 동작을 목적으로 하는 것이므로 sitecustomize.py의 영향을 받을 수 없는 것 같다.

추측은 이쯤 해 두고, 이런 경우에는 작업중인 소스파일 상단에 아래와 같이 sys.setdefaultencoding("utf-8")을 넣은 채로 py2exe로 실행파일을 만들었더니 잘 되었다. 이 방식을 쓰면 스크립트를 직접 실행할 때는 오류가 났지만, py2exe로 변환된 실행파일을 실행할 때는 오류도 안 나고 인코딩 설정도 바뀐다.

import sys
sys.setdefaultencoding("utf-8")


개발할 때는 주석처리했다가 py2exe 돌릴때만 적용하려면 귀찮아지는데, 그냥 아래와 같이 해 두면 신경 안 써도 될 것이다.

try:
    if sys.frozen:    # 참고자료 
        sys.setdefaultencoding("utf-8")
except:
    pass



스크립트를 직접 실행할 때만 이 방법에서 오류가 나는 것을 보고, 아마도 sys.setdefaultencoding("utf-8")을 넣는 것은 __main__을 포함하고 있는 최상위 스크립트에서는 안 되고, main 스크립트에서 import하는 스크립트에서만 가능한 것이 아닐까 싶어서 한 번 해 봤는데, 최상위고 뭐고 스크립트를 직접 실행할 때는 항상 오류가 났다.

결론은, py2exe를 쓸 때는 소스파일에 직접 sys.setdefaultencoding('utf-8') 식으로 넣어보니 되더라는 것이다.
이렇게 지저분하게 경험을 늘어놓는 것 말고 조리있게 배경을 설명해둔 자료가 있으면 좋겠는데 일단 여기까지만..
by 시험さま | 2011/07/05 09:43 | 컴퓨터 | 트랙백 | 덧글(4)
트랙백 주소 : http://chanik.egloos.com/tb/3685653
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
Commented by 노진희 at 2013/12/06 16:09
잘보고 갑니다.
Commented by doorto at 2014/11/20 18:02
감사합니다. 덕분에 문제를 해결했습니다.
Commented by ㅇㅇ at 2017/04/22 21:32
감사합니다! pyinstaller / python 3.7 / 사용중인데 위 소스코드를 집어넣으니 utf-8로 Sys Default Encoding 설정 되네요
Commented by 시험さま at 2017/05/04 17:22
도움이 되었다는 덧글을 보니 기분 좋네요.
그런데, 제가 뭘 잘 알고 쓴 게시물은 아니니까
너무 믿지는 마시고 잘 걸러서 쓰세요.. ^^

:         :

:

비공개 덧글

< 이전페이지 다음페이지 >