いつも使っているJupyterに関する話です。Jupyterの中では、InteractiveShellというオブジェクトが使われていて、これを利用することでさまざまな高度な操作を行うことができます。
多くのことができるのですが、最近これを使って変数を操作する機会があったのでその辺を紹介していきます。
そもそも、InteractiveShell オブジェクトとは?という話ですが、これはIPython(Jupyter Labのバックエンドとして動作する対話的なPythonシェル)の中心的なクラスです。このオブジェクトを通じて、現在のセッションの状態を取得したり、マジックコマンドを実行したりすることができます。
このInteractiveShellはget_ipython() という関数を使うことでそのnotebook自身で取得し、アクセスすることができます。
マジックコマンドの動的な実行
このInteractiveShellオブジェクトを使うと例えば、マジックコマンドをプログラムで実行したりできます。
例えば、%pwd っていう現在のでディレクトリを取得するマジックコマンドがありますが、これが次のようにして実行できます。
ip = get_ipython()
ip.run_line_magic('pwd', '')
(pwdをメソッドとして実行するメリットはなかなか薄いので例が適切でなくてすみません。)
マジックコマンドをそのままマジックコマンドととして実行するのと比べると、結果を文字列として取得して以降の処理で使えるとか、実行するコマンドをプログラムで動的に変化させて実行させることができるといった利点があります。
もちろん、 run_cell_magic() って関数もあるのでセルマジックも実行できますよ。
変数の取得や設定
今回紹介するもう一つの使い方は変数の取得や追加です。名前空間の操作といった方がわかりやすいかもしれません。
InteractiveShellオブジェクトを使って、upyter Labのセッション内で定義されている変数を取得したり、新しい変数を設定したりすることができます。
変数の取得は user_ns 属性を使います。現在定義されている変数が全部辞書として入っています。デフォルトで入ってるJupyter/IPython固有の変数も多いので、自分が宣言した覚えのないものもあると思います。
例えば次のようにして使います。
x = 10
y = "Hello"
ip = get_ipython()
print(ip.user_ns['x'])
# 10
print(ip.user_ns['y'])
# "Hello"
変数の取得としてはあまり用途ないかもしれないですね。どちらかというと既に宣言されているかどうかのチェックとかで使えるかもしれません。
逆に、次のようにして新しい変数を定義することもできます。
ip = get_ipython()
ip.push({'z': "新しい変数"})
print(z)
# 新しい変数
この例だけ見てると、 z=”新しい変数” って直接書くのと同じやん、と思えますが、この方法の利点は変数名の方もプログラムで動的に指定できることです。
まぁ、 exec(“z=’新しい変数'”) ってすれば変数名を動的に変えられるので固有のメリットというわけではないのですが、execは本当にリスクの大きな手段なのでそれよりは安全に使えるという利点があると思います。
この変数の名の指定は、関数やマジックコマンドの中で使うと、例えばユーザーが指定した変数名に結果を格納するといった応用ができます。
最近、別の場所で書いているnote記事の中で自分が自作したマジックコマンドを紹介したのですが、そこで使っているクエリの結果を引数で指定した変数に格納するのにこのip.pushを使っています。
参考: Snowflakeに手軽にSQLを打てるJupyterマジックコマンドを作ってみた
ip.push を使わずに、
ip.user_ns[‘z’] = “新しい変数”
みたいに、user_nsオブジェクトに直接突っ込んでも同じことができますので合わせて覚えておいてください。
InteractiveShellオブジェクトでできることのごく一部ではありますが、今回の記事としては以上となります。