본문 바로가기

프로그래밍/Python

[PYTHON3.6|PIP] in console_to_str return s.decode UnicodeDecodeError: 'utf-8' codec can't decode byte

반응형

pip 최신버전에서 문제가 해결되었으니, 소스를 수동으로 수정할 필요 없음. http://daewonyoon.tistory.com/245 를 참고.


Python 3.6 pip 로 특정 패키지를 설치하다 다음과 같은 에러가 발생한 적이 있다.


C:\Users\me>py -3.6 -m pip install wrapt Collecting wrapt Downloading http://---------------/packages/wrapt-1.10.8.tar.gz Installing collected packages: wrapt Running setup.py install for wrapt ... error Exception: Traceback (most recent call last): File "C:\Python3632\lib\site-packages\pip\compat\__init__.py", line 73, in console_to_str return s.decode(sys.__stdout__.encoding) UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb6 in position 67: invalid start byte During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\Python3632\lib\site-packages\pip\basecommand.py", line 215, in main status = self.run(options, args) File "C:\Python3632\lib\site-packages\pip\commands\install.py", line 342, in run prefix=options.prefix_path, File "C:\Python3632\lib\site-packages\pip\req\req_set.py", line 784, in install **kwargs File "C:\Python3632\lib\site-packages\pip\req\req_install.py", line 878, in install spinner=spinner, File "C:\Python3632\lib\site-packages\pip\utils\__init__.py", line 676, in call_subprocess line = console_to_str(proc.stdout.readline()) File "C:\Python3632\lib\site-packages\pip\compat\__init__.py", line 75, in console_to_str return s.decode('utf_8') UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb6 in position 67: invalid start byte


파이썬에서 발생하는 UnicodeDecodeError는 다양할 수 있으니, 이 글에서 제시하는 해결책이 모든 경우에 대한 해결책은 아니라는 점을 우선 주지하고, Traceback  의 마지막 줄에 해당하는 pip/compat/__init__.py 의 75번째 줄을 보면 다음과 같이 생겼다.


#=============================================================================================== 70 if sys.version_info >= (3,): 71 def console_to_str(s): 72 try: 73 return s.decode(sys.__stdout__.encoding) 74 except UnicodeDecodeError: 75 return s.decode('utf_8') #, errors='ignore') 76 77 def native_str(s, replace=False): 78 if isinstance(s, bytes): 79 return s.decode('utf-8', 'replace' if replace else 'strict') 80 return s

문제는 어떤 디렉토리 패쓰 (예를 들어, C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\BIN\\link.exe 같은 것) 또는 더 일반적으로 문자열을 콘솔의 stdout 에서 읽어들이는데, 콘솔의 인코딩이 옳지 않아서, decode 함수가 실패하여 발생하는 것이다.


당시 나는 이 문제를 decode 함수의 실패만 피해갈 수 있도록, errors='ignore' 인자를 추가하여 넘어갔다. (이 인자는 인코딩 또는 디코딩시 대응되는 문자가 없는 에러가 발생하면, 무시하고 빼놓고 진행하라 뜻.) 즉, return s.decode('utf_8') 부분을 return s.decode('utf_8', errors='ignore') 로 고쳐서 넘어갔었다.


당시에는 단순한 로깅을 위해 콘솔아웃풋을 변환하는 것이어서 "무시"하였지만, 지금 다시 살펴보니, 외부 툴의 콘솔아웃풋이 다음 동작에 크리티컬하게 영향을 미친다면, 문제가 될 수도 있는 방법인 듯 하다. 조심해서 사용하시길. 그리고, 아마 최근 최신버전에선 이 버그가 고쳐지지 않았을까?

728x90