このブログの更新は Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama

メールでのご連絡は hiyama{at}chimaira{dot}org まで。

はじめてのメールはスパムと判定されることがあります。最初は、信頼されているドメインから差し障りのない文面を送っていただけると、スパムと判定されにくいと思います。

[参照用 記事]

Pythonを使ってみた -- とりあえずJSONデータを読み込む

Kuwataさんが、料理のあいまにワシワシとPythonでプログラミングしていて、僕は眺めているだけです。眺めるために、一応Pythonコードが読めたほうがいいかな、と思ったので(イマサラかよ>自分)、Python 2.6 をいじってみました。

対話的処理系をシェルとして使う

対話的処理系を起動して、とりあえず普通のシェルのように使いたいんだけど、どうしたらいいんだろう? -- osモジュールの関数を使えばよさそうです。


>>> import os
>>> os.getcwd()
'C:\\tmp'
>>> os.listdir(".")
['#dump.c#', 'a.exe', ...(省略)...]
>>> os.mkdir("pytest")
>>> os.chdir("pytest")
>>> os.getcwd()
'C:\\tmp\\pytest'
>>> os.listdir(".")
[]

ちょっと、キータイプが大変だな。次のような関数を書いたファイルを作りました。


# -*- coding: utf-8 -*-
# shellcmd.py

u'''超簡単なシェルコマンド'''

import os

def pwd():
print os.getcwd()

def cd(dir):
os.chdir(dir)

def ls():
for f in os.listdir('.'):
print f

def mkdir(dir):
os.mkdir(dir)

import shellcmd すると定義した関数を使えますが、これだと、shellcmd.ls() と書くか、手動で from shellcmd import ls とかしないといけない。バカみたい。と思ったら、環境変数PYTHONSTARTUPを使うと、対話的処理系のスタートアップ・スクリプトを指定できるようなので、とりあえず次のようにして起動。


set PYTHONSTARTUP=shellcmd.py
python

ls() とかがすぐに使えました。対話的モードにおいてコマンドとして有用な関数群は、%HOME%\startup.py とか ~/.pythonrc.py とかにまとめて、環境変数PYTHONSTARTUPに指定しておくとよさそうです。

JSON処理ライブラリ

Python 2.6 では、標準でJSONハンドリングがサポートされているようです。jsonモジュール群の実体は、Python26/Lib/json/ に置かれていました。importしてみましょ。


>>> import json
>>> help(json)
Help on package json:

NAME
json - A simple, fast, extensible JSON encoder and decoder

...(以下省略)...

jsonライブラリのドキュメントはWebにもあります → http://docs.python.org/library/json.html

バージョン 2.5 でも使えるsimplejsonってのもあります。

標準jsonとsimplejsonの併用は次のようにするとよさげ。


# simplejsonを優先する場合
try:
import simplejson as json
except ImportError:
import json

jsonライブラリのドキュメントによると、JSONデータは、次のようにPythonネイティブデータにマップされます。

JSON Python
object dict
array list
string unicode
integer int, long
number (not integer) float
boolean bool
null NoneType

これは、非常に素直なマップですね。

JSON文字列の解析と変換

とりあえず実験。


>>> import json
>>> json_str = '{"name" : "板東トン吉", "age" : 26}'
>>> print json_str
{"name" : "板東トン吉", "age" : 26}
>>> json.loads(json_str)
Traceback (most recent call last):
File "", line 1, in
File "c:\Installed\Python26\lib\json\__init__.py", line 307, in loads
return _default_decoder.decode(s)
File "c:\Installed\Python26\lib\json\decoder.py", line 319, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "c:\Installed\Python26\lib\json\decoder.py", line 336, in raw_decode
obj, end = self._scanner.iterscan(s, **kw).next()
File "c:\Installed\Python26\lib\json\scanner.py", line 55, in iterscan
rval, next_pos = action(m, context)
File "c:\Installed\Python26\lib\json\decoder.py", line 183, in JSONObject
value, end = iterscan(s, idx=end, context=context).next()
File "c:\Installed\Python26\lib\json\scanner.py", line 55, in iterscan
rval, next_pos = action(m, context)
File "c:\Installed\Python26\lib\json\decoder.py", line 155, in JSONString
return scanstring(match.string, match.end(), encoding, strict)
UnicodeDecodeError: 'utf8' codec can't decode byte 0x94 in position 0: unexpect
d code byte

アリッ? Windowsのコマンドプロンプトからだと、日本語がシフトJISで入っているようです。JSONデータのデフォルトエンコーディングはUTF-8だから、エンコーディングのミスマッチでうまくいってないわけね。


>>> json_str
'{"name" : "\x94\xc2\x93\x8c\x83g\x83\x93\x8bg", "age" : 26}'

16進で見ると、…… ウーム、、わかんないけど、UTF-8っぽくないですね。json.loadsの第二引数に文字エンコーディングを指定できるので:


>>> json.loads(json_str, 'Shift_JIS')
{u'age': 26, u'name': u'\u677f\u6771\u30c8\u30f3\u5409'}

うまくいったみたい。得られたデータでは、文字列として、Pythonのunicodeデータが使われています。

JSONファイルのロード

今度はファイルからJSONデータを読み込んでみます。次のようなファイルを作りました。エンコーディングはUTF-8です。


{
"name" : "板東トン吉",
"age" : 26
}

ファイルから文字列(つうかバイト列)を作って、それを json.loads()(最後のsはstringのsだと思われる)で処理してもいいのですが、json.load() を使えばファイルからJSONデータをロードできます。


>>> f = open("tonkichi.json")
>>> json.load(f)
{u'age': 26, u'name': u'\u677f\u6771\u30c8\u30f3\u5409'}
>>> f.close()

次のような関数を作っておけば便利でしょう。


def load_json(fname, encoding = 'utf-8'):
with open(fname) as f:
return json.load(f, encoding)

with構文は、Python 2.6 からサポートされたものです(とか、にわか*1仕込みの知識で言ってみる ^^;)。

*1:7分くらい前。