Memo: Python3 CSVの中の1項目を文字コードShift_JISで何バイトになるか計測する
Python3の内部エンコードはUTF-8。で、スクリプト内で外部ファイルを云々するときに encoding="utf8" で作業しているとする。このとき、文字列のバイト数を測ると、当然ながらUTF-8文字列のバイト数として測ることになる。
スクリプト内ではUTF-8で作業しているけれども、対象の文字列をWindowsのShift_JIS(またの名をcp932、もしくは、Windows-31J)という文字コードとして認識し直してバイト数を測りたい、というシチュエーションが発生した。
某ECサイトにCSVで商品データを登録する際、Shift_JISで保存したCSVを使うのだ。
そのサイトのシステムは、素朴にCSVファイル上の項目をバイトで測る。
どういうことかと言うと、人間の目視で下記のような文字があったとする。
これは"私"の感覚であり、"あなた"の感覚とは違うかも知れない。
そうではないか?
これは某ECサイトのCSV認識システムでは下記のように認識される。
"これは""私""の感覚であり、""あなた""の感覚とは違うかも知れない。\r\nそうではないか?"
これをUTF-8ではなくてShift_JISでバイト数カウントする。
なぜそんな作業をするのかと言うと、商品情報をECサイトに登録する際、各々のフィールドには文字数・バイト数の上限値が決められているからだ。無限に大きなデータを登録できるわけではない。つまり、ECサイトに商品を出品しよう、その出品作業をプログラミングで自動化しようとする際、自動化プログラム中で文字数・バイト数をカウントする機能の実装はつきものとなる。
Python3の str.encode() メソッドを使う。また、変換エラーが起きてもほしいのはバイト数だけなのでそこで処理を中断したりせず、単になにかの文字に置き換えて続行してもらう(そういうオプションとして "replace" が用意されている)。
具体例を示す。
>>> s = '''これは"私"の感覚であり、"あなた"の感覚とは違うかも知れない。
... そうではないか?'''
>>> print(s)
これは"私"の感覚であり、"あなた"の感覚とは違うかも知れない。
そうではないか?
# 上記の文字列 s をCSVフォーマットに変換
>>> csv_s = '"{}"'.format(s.replace('"', '""').replace("\n", "\r\n"))
# この時点で len 関数を使用すると、「文字数」(バイト数ではない)を返す
>>> len(csv_s)
48
# Shift_JISに変換して len 関数を使用すると、「バイト数」(文字数ではない)を返す
>>> sjis_len = len(csv_s.encode("shift_jis", "replace"))
>>> print(sjis_len)
84
このようにいろいろ癖があるが、目的は果たせる。
参考:
Python3 標準ドキュメント
Unicode HOWTO
https://docs.python.org/ja/3/howto/unicode.html
str.encode()
https://docs.python.org/ja/3/library/stdtypes.html#str.encode
標準エンコーディング
https://docs.python.org/ja/3/library/codecs.html#standard-encodings
自分の過去記事
Python テキストストリームへ書き出す
http://basicwerk.com/memoize2/index.cgi?python.io.StringIO.txt