Stimulator

機械学習とか好きな技術話とかエンジニア的な話とかを書く

xonshの過去のコマンド履歴を可視化する

- はじめに -

この記事は、Xonsh Advent Calendar 2017 - Qiitaの6日目の記事です。

せっかくxonshではMatplotlibが使えたりするので、Command履歴の分析等の補助をする関数を書いてメモしておきたいと思います。


 

- xonshのhistory -

xonshの過去の入力履歴は以下で呼び出す事ができます。

__xonsh_history__

実際には、xonshのコマンド履歴は以下のようにSession毎にjsonファイルで管理されています。

history file
# ~/.local/share/xonsh/xonsh-7305fb13-34ea-44fd-9845-197fe015359d.json

さっそくの余談ですが、このバックエンドにsqliteを指定する事も可能です(Tutorial: History — xonsh 0.6.0.dev151 documentation)。


__xonsh_history__で得られるxonsh.history.json.JsonHistoryオブジェクトは、Commandの履歴を取得するためのメソッドを2種類持っています。

__xonsh_history__.items()    # 今のSessionでのHistory
__xonsh_history__.all_items()    # 過去全てのSessionでのHistory

どちらもIteratorが返ってくるので、例えば現在過去全てのコマンド履歴を取得するには以下のように

for x in __xonsh_history__.all_items():
    print(x["inp"])

Reference : History Backend JSON – xonsh.history.json — xonsh 0.6.0.dev151 documentation


また、jsonを直接読みにいく事ももちろんでき、xonshのhistory.jsonを直接読みに行くスクリプトは、アドベントカレンダー内の以下の記事でも既に書かれています。

qiita.com


 

- 過去のコマンドを可視化 -

以下の記事でも利用したitermplotパッケージを利用して、iTerm2上にインラインに表示してみます。
導入や綺麗な表示の仕方は以下記事で。
(以下記事内にiTerm2以外の方法も一応記述しています)
vaaaaaanquish.hatenablog.com


空白で区切られた最初のコマンド部分が10文字以下のものをCounterに投げてMatplotlibに可視化します。

import itermplot
import matplotlib.pyplot as plt
import numpy
from collections import Counter

data = Counter([x["inp"].split(" ")[0] for x in __xonsh_history__.all_items() if len(x["inp"].split(" ")[0])<10])
labels, values = zip(*data.items())
indexes = np.arange(len(labels))

plt.figure(figsize=(20,10))
plt.bar(indexes, values, width)
plt.xticks(indexes, labels, rotation='vertical')
plt.show()

結果がxonshコンソール上で見えます
f:id:vaaaaaanquish:20171206225049p:plain


ちょっと業務で使ったものを削った結果を出していますが、これは恥ずかしいですね。

xonshなのでimportやforが多いのは当たり前ですが、ls しすぎだし、X, Yといった変数を使っていたり、果にはexitもかなり使っています。xonshが嫌いなのでしょうか。
これがまだ手元のMacなので良いですが、普段はリモートサーバで作業しているので、そちらではより酷いものが見れると思います(公開はしないですが)。


しかし、これでlsというコマンドにめちゃくちゃ時間を取られている事が分かりました。lsは基本的には自動的に発動するようにしていくのが吉という事ですね。

 
 
ついでなので最も多いimportから、何を多く使っているか見てみます。

data取得箇所を変えてやれば実現できそうです。

data = Counter([x["inp"].split(" ")[1] for x in __xonsh_history__.all_items() if x["inp"].split(" ")[0]=="import"])

 
import time, plt, mathが多そう。xonshrcに書いておいて事前importするようにすれば私の仕事も減りそうです。
f:id:vaaaaaanquish:20171206230255p:plain


 

- おわりに -

ギリギリ滑り込みセーフで記事を書きましたが何とかなりました。

もうちょっと分析らしいところまで行きたかったのですが、(見せてもOKそうな)Historyが以外に少なく、時間も微妙だったので断念しました。
まあでもギリギリでも可視化まで出来たのは、Pythonという言語がシェルで扱える事の利点でもあるなと思いました。

今まで使っていたzshのログのconvertとか前後のコマンドを確認とかまでやれれば良かった…が、アドベントカレンダーに空きを見つけて書きたいと思います。


それでも全然空きがありそうなので、xonsh試したい方でも是非ご参加下さい!!

qiita.com