Windows のカレントなコードページを Python から知る方法

これでしれーっとやっちゃってるんだけれど。

これはまぁ「コードページを知るためのもの」ではないからね、そこでは触れなかったんだけれど、別件でまた必要になったついでに一応触れておこうかと。

まず、「公式 CPython Windows 版」の場合は、まぁこれで事足りるハズ:

1 Python 2.7.9 (default, Dec 10 2014, 12:28:03) [MSC v.1500 64 bit (AMD64)] on win32
2 Type "help", "copyright", "credits" or "license" for more information.
3 >>> import sys
4 >>> sys.getfilesystemencoding()
5 'mbcs'

ファイルシステムエンコーディング」で事足りるの? 事足りるでしょう。システム内で一貫してるんだから。またこれは「コードページを知る」ことにはなってはいないけれど、問題ないわけである、「そうするニーズは実際にはない」んだから。つまり「いつでも mbcs を必要な場合に encode、decode に渡せる」のだから。

同じ Windows でも「cygwin 版 CPython」「msys2 版 CPython」では事情が違ってくる。msys2 版も cygwin 版もこうなる:

1 Python 2.7.13 (default, Feb 14 2017, 14:46:01)
2 [GCC 6.3.0] on msys
3 Type "help", "copyright", "credits" or "license" for more information.
4 >>> import sys
5 >>> sys.getfilesystemencoding()
6 'UTF-8'

行儀悪いったらないと思う。「郷に入っても郷に従うものか」、とオレ流をあくまで貫こうとする。もちろん普通の Windows アプリケーションを主食にしてれば当然そう思うけれど、msys2 も cygwin も「自分は unix だ」と思い込んでいたいわけだし、この中のアプリケーションにとっては「それこそがありがたいこと」だったりもするわけで、痛し痒し、としか言いようがない。

実際はもう一つある。「じゃぁ固定値で mbcs 使っちゃえばいいじゃん」が、msys2、cygwin には通用しない。なぜなら「mbcs は Windows 版固有のコーデック」なので、「unix だと思い込んでいる cygwin、msys2」には適用されない。つまり mbcs を使えない。代わりに「cpNNN」(日本語版 Windows なら cp932) は使える。ゆえ、どうにかしてこの「cpNNN」を知る必要がある。そう、ここでやっと「コードページを知る必要がある」。

これへの「msys2/cygwin ワールドにクローズドな解」はない。ゆえ、「恐怖の DOS コマンド」に頼らなければならない:

 1 from __future__ import unicode_literals
 2 
 3 import os
 4 import sys
 5 import re
 6 import subprocess
 7 
 8 
 9 if sys.platform in ("win32", "msys", "cygwin"):
10     _ENCODING_IN = "mbcs"
11     if sys.platform in ("msys", "cygwin"):
12         # msys2 and cygwin don't have mbcs codec,
13         # but they have "cp*", so try to detect
14         # codepage of your windows.
15         _dosmes = os.environ["COMSPEC"].replace("\\", "/")  # cmd.exe
16         _chcp = subprocess.check_output(
17             [_dosmes, "/c", "chcp"]).decode("quopri") 
18         # ↑日本語版 Windows だとバリバリ日本語で返ってくる、ので quopri
19         _ENCODING_IN = "cp" + re.match(r".*: (\d+)$", _chcp.strip()).group(1)

subprocess が「Windows native のバックスラッシュ区切り」を頑なに拒絶し、かつ、「os.sep」を使えない(だって「/」だもん)てところも絶妙に鬱陶しかったりもするが、ともあれここまでやってようやく「cp932」を得られる。