概要
シェルから実行した場合とJupyterから実行した場合で実行するコードを分けたいという要望に応えるために,Pythonコードが実行されている環境を識別する関数を作りました.
類似の記事がないか検索してもPython環境構築に関する記事ばかりが引っかかったので,備忘録も兼ねて投稿します.
背景
私たちのサークルでは,Pythonで書かれたプログラムの開発環境として,主にVisual Studio + Python Tools for Visual Studioを利用しています.試行錯誤的にPythonコードを試す場合はJupyter Notebookも併用します.その際,Visual Studio用のコードとJupyter用のコードを切り替える必要が出てきます.
具体的には,アニメーション表示の処理です.我々の作るコードは時間発展する物理現象を解く事が主であり,アニメーション表示は何ステップかに一度呼び出され,結果を確認するために利用されます.そのため,アニメーションの表示にはmatplotlibのFuncAnimationではなく,canvas.blitを利用しています.Juypterで表示をする際は,display.displayとdisplay.clear_outputを併用しています.
いちいちコメントアウトやアンコメントを繰り返すのが億劫になったので,Pythonコードが実行される環境をプログラム内部から識別できればコードの共通化が実現できると考えました.
実装
参考にしたのはstackoverflowの次の記事です.
How can I check if code is executed in the IPython notebook?
ページ中程のGustavo Bezerra氏の回答によると,次の関数?が利用できると書かれていました.
get_ipython().__class__.__name__
この関数の挙動は
-
- IPython(terminal)の場合は戻り値が’TerminalInteractiveShell’
-
- Juypter(notebookとqtconsole)の場合は戻り値が ‘ZMQInteractiveShell’
- 失敗する(シェルから実行されている)とNameErrorが投げられる
となっているようです.
回答例では,IPythonから実行されているかどうかをTrue/Falseで返していましたが,私たちの要求に応えるために,実行環境の名前を文字列で返すように修正しました.関数名は安直にgetEnvironmentとしています.
def getEnvironment():
try:
env = get_ipython().__class__.__name__
if env == 'ZMQInteractiveShell':
return 'Jupyter'
elif env == 'TerminalInteractiveShell':
return 'IPython'
else:
return 'OtherShell'
except NameError:
return 'Interpreter'
get_ipython().__class__.__name__の戻り値をenvに代入し,それが’ZMQInteractiveShell’と一致すれば文字列’Jupyter’を返し,’TerminalInteractiveShell’と一致すれば文字列’IPython’を返します.それ以外の場合には’OtherShell’という文字列を返すようにしましたが,JupyterおよびIPython以外の枠組みに分類されるインタラクティブ環境が存在しているかは知りません.
NameErrorが投げられた場合はOSのシェルから実行されていると判断し,文字列’Interpreter’を返しています.
テスト
以下の環境でテストし,所望の値が返ってくるかを確認しました.
-
- Anaconda3 4.2.0.0 64bit
-
- Python 3.5.2
-
- Jupyter 4.2.0
-
- IPython 5.1.0
- Python Tools for Visual Studio 2.2.31124.00
Jupyterでのテスト
IPythonでのテスト
IPythonで実行する予定はないのですが,折角なので実行しておきます.
OSのシェル(Visual Studio)での動作テスト
無事’Interpreter’と表示されたので,私たちの要望がかなえられそうです.
まとめ
本記事ではPythonコードが実行されている環境を識別するための関数を作成しました.これでJupyterで開発するコードとVisual Studioで開発するコードを共通化することができそうです.
アニメーションの表示にcanvas.blit,あるいはdisplay.displayとdisplay.clear_outputを利用することの是非については議論しませんが,機会があればその辺りも調査したいと思います.
関数定義
最後に,ヘルプも含めた関数の定義を示します.
def getEnvironment():
'''
To confirm the environment on which the python script calling this function is running.
This function returns environment's name as String
Input
None
Output
'Jupyter' : runs on Jupyter
'IPyhon' : runs on IPython interactive shell
'OtherShell' : runs on Other type interactive shell, I don't know that such shells exist though
'Interpreter' : runs on System shell with Python interpreter
'''
try:
env = get_ipython().__class__.__name__
if env == 'ZMQInteractiveShell':
return 'Jupyter'
elif env == 'TerminalInteractiveShell':
return 'IPython'
else:
return 'OtherShell'
except NameError:
return 'Interpreter'