pickleデータをちょこちょこ見るスクリプト

2 min read読了の目安(約2200字

Pythonでpickle漬けにしたデータの扱い

pythonを使う時、データを難も考えずにディスクに保存できるpickle。
大変重宝するのですが、保存したデータを見ようとするときにちとめんどい。
そんなときのtips

シンプルに表示

openしてpickle.loadして、printするスクリプトを作ろうかと思ってたのですが、、、
流石にちゃんとあるんですね。。

https://qiita.com/yagays/items/3dd084469a7444714695

ちょっとコマンドが長いですが、alias作っとけばいいだけですね。

色々する場合

単純に表示するなら上記で良いのですが、複雑目なjson(というか多層のdict)を保存していてインタラクティブに操作して中身を見たいとか、class instanceを保存しててそれを呼び出して操作したといった時ための方法をもうちょっと考えてみます。

データ読み込み後に、対話環境を呼び出す

色々しようとするなら、なにかしらの変数(dataとしましょうか)にpickle.loadして、その状態で対話環境を起動してユーザに渡す、という方法を思い付きます。
この実現方法を調べてみました。

ipythonから呼び出す

pythonでパワフルで使いやすい対話環境といったらやはりコレ。
dateにpickleしたデータを読み込んだ状態でipythonを読み込めればゴール。

で、ちょっと調べてみたのですが、、
以下でできそうです。

$ ipython -i -c "import pickle; fd = open(<対象ファイル名>, 'rb'); data = pickle.load(fd)"

-iは、処理後に対話環境に入った状態でstopする。
-cは、与えた引数のコマンドを実行する。

クラスインスタンスを呼び出す場合は、先に該当クラスをちゃんとimportしておかなとエラーになるので、該当classを定義しているモジュールをimportする必要が出てきます。
そこまで行くと、ワンライナーにする旨味もあんま無いなぁ。。

ちなみにワンライナーにこだわらんと、処理をhogehoge.pyに書き込んでる場合は、

$ ipython -i ./hogehoge.py

でOK。

ipython”を”呼び出す

逆に、.pyファイルを作成して、処理一通りした後にipythonを呼び出す方法もあるのですね。
こんな。

import pickle
import IPython


with open(<対象ファイル>, 'rb') as fd:
    data = pickle.load(fd)
    
IPython.start_ipython(user_ns=locals())

start_ipythonがipythonの対話環境を呼び出すコマンド。
引数を何も与えないと前の処理を難も引き継いでくれないので、user_nsに対してlocals()で、直前のネームスペース情報を全部ぶん投げるという力技。
class instanceをpickleから読み出すときは大体用途も限られるでしょうから、上記のようなpythonファイル作っちゃうほうがいいのでしょうね。

ただし、、、ファイル名を引数で取れるようにと、argparseを追加すると、、、

ValueError      Traceback (most recent call last)
/usr/lib/python3.8/codeop.py in __call__(self, source, filename, symbol)
    140     def __call__(self, source, filename, symbol):
--> 141         codeob = compile(source, filename, symbol, self.flags, 1)
    142         for feature in _features:
    143             if codeob.co_flags & feature.compiler_flag:

ValueError: source code string cannot contain null bytes

えぇぇ、、、
argparse単独/IPython単独だったらうまく行くのですが、、
微妙なバージョンの問題な気がしますが、ちと突き詰めるの辛いんで、ほっときたい。。

別の対話環境 xonsh

pythonコマンドが使えるshellであるところのxonsh。
gitsomeで使ってるらしいので、そんな感じでipythonの代わりに使えないかなと。

。。結果として、namespace引き継い打状態でxonshを起動する方法が見つけられず。
起動自体は以下でできるのですが。

from xonsh import main


main.main()

まとめ

単純な呼び出し+対話環境なら、ipython -i -cで。
複雑目なら、事前にhogehoge.pyを作って、ipython -i hogehoge.pyで。