文字列、Byte、Binaryが混乱していたので、ちょっと自分の整理のため。
PythonでByte列を扱う場面は、(1)外部のプログラム等とバイト列で文字列をやりとりする場合(文字列をJsonなどで送受信するとき)、(2)RaspberryPiなどを用いたGPIOの制御の場合。特に、制御系では、Python2のコードも多く、文字列とByte列の区別が明確でなかった(文字列とByte列の結合が容易にできる)が、Python3では扱いが厳密になっている。
参考:Python2とPython3での文字列、バイト列の扱いの違い
### 1. ビットとバイトについて
基本ですが、
ビット:2進数(0と1、バイナリ)で表した数字の桁数。
4ビットのデータ(4桁の2進数)は 0~15 までの16通りの数字を表すことができる(2の4乗=16)。
8ビットのデータ(8桁の2進数)は 0~255 までの256通りの数字を表すことができる(2の8乗=256)。
バイト:8ビットで1バイト。1バイト(256通り)の数字を表すのに16進数を使うと便利。
256=16×16なので,1バイトの数字がちょうど2桁の16進数で表せる。
参考:
ビットとバイトの違いが覚えられない・・・。 - 中央線に乗って考える
コメントいただいたshiracamusさんの記事です。バイナリーのことが詳しく書かれています。
プログラムとバイナリ
2. 文字コード
各文字に割り当てられるバイト表現。
参考:文字コード
Wiki引用:
文字コードは文字の集合の各文字に一意なバイト表現を割り当てただけのシンプルなものだった(アスキーコードなど)。バイト値を計算によって変形した符号化表現が用いられるようになってきたため(例えば Shift_JIS や UTF-8)、「符号化文字集合」と「文字符号化方式」とを区別するようになったと考えられる。
ASCIIコード:英語圏などで使われる限られた文字集合(7ビットを使用し最大128文字。)
Unicorde:世界中の文字を単一文字集合として扱う符号化文字集合
参考:Python2がベースですがUnicodeについて書かれています。
3. 符号化
UTF-8:Unicordeを可変長(1-4バイト)の8ビット符号単位で表現する文字符号化スキーム。ASCIIに対して上位互換している。(一番使われている方式)。他の方式もある。
Base64:データを64種類の印字可能な英数字のみを用いて、それ以外の文字を扱うことの出来ない通信環境にてマルチバイト文字やバイナリデータを扱うためのエンコード方式。MIMEによって規定されていて、7ビットのデータしか扱うことの出来ない電子メールにて広く利用されている。
### 4. Python3における文字列、バイト列への変換
主に(1)の用途で用いられる。python3で文字列はユニコードに統一されている。
例、日本語の’あ’と、英語の'a'のUnicodeの値
#Unicode 文字を表す文字列に対し、その文字のUnicode コードポイントを表す整数を返す。
>>> ord("あ")
12354
>>> ord("a")
97
#()内の整数を"0b"のついた2進文字列に変換
>>> bin(ord("あ"))
0b11000001000010
>>> bin(ord("a"))
0b1100001 #7bit
#()内の整数を"0x"のついた16進文字列に変換
>>> hex(ord("あ"))
0x3042 #16進数に変換 3042 ユニコード表と一致
>>> hex(ord("a"))
0x61 #16進数に変換 0061 ユニコード表と一致
#()内がUnicode コードポイントの整数に対し、文字列を返す。
>>> chr(ord("あ"))
あ
>>> chr(12354)
あ
>>> chr(ord("a"))
a
>>> chr(97)
a
#UTF-8で符号化してByte列で出力
>>> "あ".encode()
b'\xe3\x81\x82'
>>> "a".encode()
b'a'
#Byte列を文字列に戻す
>>> b'\xe3\x81\x82'.decode()
あ
>>> b'a'.decode()
a
参考:文字列とバイト列の相互変換について
Python 3 での文字列とバイト列の相互変換と16進数表示
例:base64への変換
import base64
s = "あ".encode()
ss= "a".encode()
#Byte列しか受け付けません。
t = base64.b64encode(s)
tt = base64.b64encode(ss)
print(t)
#b'44GC'
print(tt)
#b'YQ=='
### 5. Python3での数字の表し方
10進数 97
16進数 0x61
2進数 0b1100001
参考:2進数/10進数/16進数/文字列の変換
参考:2進数/10進数/16進数/文字列の変換や演算など
Pythonで2進数、8進数、16進数の数値・文字列を相互に変換
5. Binaryデータ
主に(2)の用途で用いる。主に用いられるモジュールはstruct, binascii。
バイナリーデータでは、コンピューターのプロセッサーがどのようにバイトに分割するかのエンディアンや整数の符号ビットなどの概念を知っておく必要がある。
struct モジュールは、細かくフォーマットを指定してバイナリデータを作成したり、バイナリデータから数値等に変換を行うことができます。Cのデータ型とpythonのデータ型の相互変換に利用できる。
binasciiモジュールは、バイナリと ASCII コード化されたバイナリ表現との間の変換を行うための多数のメソッド提供している。
参考:structモジュールを使う方法とctypes.Structureクラスを使う方法の解説
struct - パックされたバイナリデータとしてバイトを解釈する
例:binascii
import binascii
>>> binascii.hexlify('a'.encode())
# => b'61'
>>> binascii.b2a_hex(b'a') #ASCIIコードのみ b’ASCII文字列’でバイナリーとして認識する。
# => b'61'
>>> binascii.hexlify('あ'.encode('utf-8'))
# => b'e38182'
>>> binascii.b2a_hex('あ'.encode('utf-8'))
# => b'e38182'