예외가 발생한 이유는 파일을 열 때 이진 쓰기 모드('wb')가 아닌 텍스트 쓰기 모드('w')로 열었기 때문이다. 파일이 텍스트 모드인 경우 write 연산은 이진 데이터가 들어 있는 bytes 인스턴스가 아니라 유니코드 데이터가 들어 있는 str 인스턴스를 요구한다. 이 문제는 'wb' 모드를 사용해 파일을 열면 해결할 수 있다.
with open('data.bin', 'wb') as f: f.write(b'\xf1\xf2\xf3\xf4\xf5')
파일에서 데이터를 읽을 때도 비슷한 문제가 발생할 수 있다. 예를 들어 위에서 기록한 이진 파일을 읽으려고 시도할 때 다음과 같은 오류가 발생한다.
with open('data.bin', 'r') as f: data = f.read() >>> Traceback ... UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf1 in position 0: invalid continuation byte
파일을 열 때 이진 읽기 모드('rb')가 아닌 텍스트 읽기 모드('r')로 열었기 때문이다. 핸들이 텍스트 모드에 있으면 시스템의 디폴트 텍스트 인코딩을 bytes.encode(쓰기의 경우)와 str.decode(읽기의 경우)에 적용해서 이진 데이터를 해석한다. 대부분의 시스템에서 디폴트 인코딩은 UTF-8인데, UTF-8 인코딩은 b'\xf1\xf2\xf3\xf4\xf5'라는 이진 데이터를 받아들일 수 없기 때문에 위와 같은 오류가 발생한다. 이 문제는 파일을 'rb' 모드로 열면 해결할 수 있다.
with open('data.bin', 'rb') as f: data = f.read() assert data == b'\xf1\xf2\xf3\xf4\xf5'