파이썬은 문자열 데이터의 시퀀스를 표현하는 두 가지 타입이 존재하는데 그것은 bytes와 str이다.
a = b'i am bytes'
print(a)
print(type(a))
--> b'i am bytes'
--> <class 'bytes>
something = 'hello world'
this = something.encode('utf-8')
print(type(this))
-> <class 'bytes'>
print(type(this.decode('utf-8')))
-> <class 'str'>
파이썬으로 문자를 표현할 때마다 타입이 두 가지로 나눠져 있기 때문에 자주 발생하는 두 가지 문제가 있다.
- utf-8로 인코딩된 8비트 시퀀스를 그대로 쓰고 있을 때
- 특정 인코딩을 지정하지 안은 유니코드 문자열을 쓰고 싶을 때
def always_str(bytes_or_str):
if isinstance(bytes_or_str, bytes):
value = bytes_or_str.decode('utf-8')
else:
value = bytes_or_str
return value
print(repr(always_str(b'foo')))
실행결과
-> 'foo'
print(repr(always_str('foo')))
실행결과
->'foo'
def always_str(bytes_or_str):
if isinstance(bytes_or_str, str):
value = bytes_or_str.encode('utf-8')
else:
value = bytes_or_str
return value
print(repr(always_str(b'foo')))
실행결과
-> b'foo'
print(repr(always_str('foo')))
실행결과
-> b'foo'
얼핏 보기에는 bytes와 str은 똑같이 작동한다. 하지만 bytes와 str은 서로 다른 인스턴스이기 때문에 호환이 되지 않는다. 그래서 전달되는 문자 시퀀스 타입을 정확하게 알아야 한다.
- str과 bytes는 더할 수 없다.
- bytes와 str은 비교할 수 없다.
- 연산자는 각 타입의 형식화 문자열에 대해 작동한다.
파일 핸들(내장함수 open)과 관련된 연산들은 디폴트로 유니코드 문자열을 요구하지 이진 바이트를 문자열을 요구하지 않는다.
with open('data.bin', 'w') as f:
f.write(b'\xf1\xf2\xf3\xf4\xf5)
이런식으로 하면 에러가 발생한다. 만약 이진 데이터를 열고 쓰거나 열고 싶은면 'wb','rb'로 열어야 한다.
with open('data.bin', 'w',encoding='cp1252') as f:
f.write(b'\xf1\xf2\xf3\xf4\xf5)
이러한 방식으로 인코딩 방식을 설정해서 열 수 있다.
Effective python을 참고해서 작성했습니다.