この記事では、PythonでBytesをStringに変換する方法について見ていきます。この記事の終わりには、これらの型が何であるか、そしてそれらを使って効果的にデータを処理する方法について明確な考えを持つようになります。
使用しているPythonのバージョンによって、この作業は異なります。Python 2は寿命が尽きましたが、多くのプロジェクトでまだ使われているので、Python 2とPython 3の両方のアプローチを含めて説明します。
Python 3でバイトを文字列に変換する。
Python 3以降、古いASCIIのやり方は消え去り、Pythonは完全にUnicodeになりました。
これは、明示的なUnicodeの型がなくなったことを意味します。u “string”- すべての文字列は
u “string”` です!
これらの文字列を古き良きバイト列と区別するために、新しい文字列の指定子である b "string"
が導入されました。
となります。
これはPython 2.6で追加されましたが、2.6ではすべての文字列がバイト列だったので、Python 3を準備する以外の本当の目的はありませんでした。
Python 3 のバイト列は正式には bytes
と呼ばれ、0 <= x < 256 の範囲にある不変の整数の列となります。2.6 で追加されたもう一つの bytes
に似たオブジェクトに bytear
があります。
decode()でバイトを文字列に変換する
bytesクラスの組み込みメソッドである
decode()` を使って、バイトを文字列に変換する方法を見てみましょう。
>>> b = b"Lets grab a xf0x9fx8dx95!"
# Let's check the type
>>> type(b)
<class 'bytes'=""
# Now, let's decode/convert them into a string
>>> s = b.decode('UTF-8')
>>> s
"Let's grab a !"
エンコード形式を渡して、bytes
オブジェクトを文字列にデコードし、それを表示しています。
コーデックを使ってバイトを文字列に変換する
あるいは、ビルトインの codecs
モジュールを使ってもよいでしょう。
>>> import codecs
>>> b = b'Lets grab a xf0x9fx8dx95!'
>>> codecs.decode(b, 'UTF-8')
"Let's grab a !"
エンコーディングのパラメータを渡す必要はありませんが、渡すことが推奨されます。
>>> codecs.decode(b)
"Let's grab a !"
str()でバイトを文字列に変換する。
最後に、様々な値を受け取って文字列に変換する str()
関数を紹介します。
>>> b = b'Lets grab a xf0x9fx8dx95!'
>>> str(b, 'UTF-8')
"Let's grab a !"
ただし、str()
の引数には必ずエンコーディングを指定してください。そうしないと、予期しない結果が得られるかもしれません。
>>> str(b)
b'Lets grab a xf0x9fx8dx95!'
ここで再びエンコーディングの話になります。間違ったエンコーディングを指定すると、最悪の場合、データがデコードできずにプログラムがクラッシュしてしまいます。例えば、 str()
関数を UTF-16
で使おうとすると、次のように表示されるでしょう。
>>> str(b, 'UTF-16')
'敌❴u2073牧扡愠uf020趟'
Python 3がUnicodeを前提としていることを考えると、これはさらに重要なことです。
Python 2でバイトを文字列に変換する。
Python 2では、バイトの束と文字列は実質的に同じものです。文字列は1バイト長の文字からなるオブジェクトで、各文字は256の値を格納できることを意味します。そのため、文字列はバイト列と呼ばれることもあります。
このため、バイト列と呼ばれることもあります。バイト列のデータを扱うときは、変数に読み込むだけで印刷の準備が整います。
>>> s = "Hello world!"
>>> s
'Hello world!'
>>> len(s)
12
しかし、バイト列にユニコード文字を使用すると、この動作が少し変わります。
>>> s = "Let's grab a !"
>>> s
'Lets grab a xf0x9fx8dx95!'
# Where has the pizza gone to?
>>> len(s)
17
# Shouldn't that be 15?
バイトをユニコードに変換する (Python 2)
ここでは、Python 2 の Unicode
型を使う必要があります。これは Python 3 で想定され、自動的に使われます。これは文字列をバイトではなく、一連のコードポイントとして格納します。
PythonはバイトをASCII文字として表現する方法を知らないので、xf0x9f, x8d, x95
は2桁の16進数として表現します。
>>> u = u"Let's grab a !"
u"Let's grab a U0001f355!""
>>> u
"Let's grab a !"
# Yum.
>>> len(u)
15
上で見たように、Unicode文字列は `U0001f355
を含んでいます。これはUnicodeエスケープ文字で、端末はピザのスライスとしてプリントアウトする方法を知っています! この設定は、バイト列の値の前に u
指定子を使用することで簡単に行うことができます。
では、どのように2つを切り替えるのでしょうか?
バイト列をデコードすることで、Unicode文字列を得ることができます。これは、Unicodeオブジェクトを構築して、バイト文字列とエンコーディング名を含む文字列を引数として与えるか、バイト文字列に対して .decode(encoding)
を呼び出すことで実現可能です。
decode()を使ってバイトを文字列に変換する (Python 2)
また、codecs
モジュールの codecs.encode(s, encoding)
を使うこともできます。
>>> s = "Let's grab a xf0x9fx8dx95!"
>>> u = unicode(s, 'UTF-8')
>>> u
"Let's grab a !"
>>> s.decode('UTF-8')
"Let's grab a !"
コーデックを使ってバイトを文字列に変換する(Python 2)
または、codecs
モジュールを使用する。
import codecs
>>> codecs.decode(s, 'UTF-8')
"Let's grab a !"
エンコードに気をつける
バイトはエンコーディングによって解釈が変わることがあるので、注意が必要です。約80種類のエンコーディングが用意されているため、正しいエンコーディングかどうかを判断するのは簡単ではありません。
s = 'xf8xe7'
# This one will let us know we used the wrong encoding
>>> s.decode('UTF-8')
UnicodeDecodeError: 'utf8' codec can't decode byte 0xf8 in position 0:
invalid start byte
# These two overlaps and this is a valid string in both
>>> s.decode('latin1')
øç
s.decode('iso8859_5')
јч
元のメッセージは øç
か јч
のどちらかで、どちらも有効な変換であるように見えます。
結論
プログラマーとして、落とし穴を避けるために常に考え、積極的に準備しなければならないことがいくつかあります。これは、Pythonのような高級言語を日常的に使っているときにはめったに行かないような、低レベルな部分について特に当てはまります。
文字セット、エンコーディング、バイナリといったものは、私たちの仕事がコーディングであること、つまり、私たちの考えを実用的なソリューションにエンコードすることであることを私たちに思い出させるために存在します。ありがたいことに、キーボードを何度か叩いているうちに、この考え方の多くが日課になります。
この記事では、Pythonでバイトを文字列に変換する方法について説明します。
</class