通常の Python 例外フックを呼び出す前に、キャッチされなかったすべての例外をコードに記録するための例外ハンドラを作成しました。Python と iPython では、これを行う方法が少し異なります。私が見つけたのは、iPython の方法は、インタラクティブ セッション内から実行した場合、または「.ipy」ファイル名拡張子を使用した場合にのみ機能するということです。「マジック」を使用しているとは思わないにもかかわらず、スクリプトの名前が.pyで「Pure python」であっても、通常のpythonの方法はipython内では機能しません。
コマンドラインから「.py」ファイルとして呼び出された場合でも、スクリプト内から iPython の独自の例外フックを設定できる方法が必要です。
コード例 testcase.py:
import sys
def my_exc(exc_type, exc_value, exc_traceback):
"""Regular Python exception handler with inputs mirroring sys.excepthook"""
print('\nDoing Custom Stuff (Python exc handler)\n')
# Call the old sys.excepthook as well
sys.__excepthook__(exc_type, exc_value, exc_traceback)
def imy_exc(shell, exc_type, exc_value, exc_tb, tb_offset=None):
"""IPythonic exception handler, following instructions in
set_custom_exc here:
http://ipython.org/ipython-doc/stable/api/generated/IPython.core.interactiveshell.html"""
print('\nDoing Custom Stuff (iPython exc handler)\n')
# Do regular IPython stuff as well
shell.showtraceback((exc_type, exc_value, exc_tb), tb_offset=tb_offset)
try:
__IPYTHON__
from IPython import get_ipython
shell = get_ipython()
if shell:
print('Shell Active')
# Set my custom exception handler for the current IPython shell
get_ipython().set_custom_exc((Exception,), imy_exc)
else:
print('In IPython, but no active shell')
sys.excepthook = my_exc
except NameError:
print('NameError, falling back on regular Python way')
# use the standard python excepthook override
sys.excepthook = my_exc
def makeproblem():
1/0
makeproblem()
行動:
作品:
1. $ ipython testcase.ipy
- result: "shell active", "Doing Custom Stuff (iPython exc handler)""
2. $ ipython -c="execfile('testcase.py')
- result: "NameError, falling back on regular Python way", "Doing Custom Stuff (Python exc handler)" (This one is particularly puzzling)
3. $ python testcase.py
- result: "NameError, falling back on regular Python way", "Doing Custom Stuff (Python exc handler)"
4. $ ipython
In[0]: execfile('testcase.py')
or
In[0]: %paste #pasting testcase.py
- result: "shell active", "Doing Custom Stuff (iPython exc handler)""
動作しません:
1. $ ipython testcase.py
- result: "Shell Active", no override statement
2. $ ipython -c="% run 'testcase.py'"
- result: "Shell Active", no override statement
%run vs execfile の動作は、自己完結型の名前空間で実行されているスクリプトと関係があることを示唆していますが、それを理解することはできませんでした. ただし、これはニシンかもしれません。私が持っている他のヒントは、上記のテストケーススクリプトでインスペクトを使用してフレームをダンプすると、動作するケースの上部にインタラクティブシェルへの次の呼び出しがあり、それ以外の場合は表示されないということです:
(<frame object at 0x10264b500>, '/Library/Frameworks/EPD64.framework/Versions/7.3/lib/python2.7/site-packages/IPython/core/interactiveshell.py', 2883, 'run_code', ['exec(code_obj, self.user_global_ns, self.user_ns)\n'], 0)
(<frame object at 0x10264a790>, '/Library/Frameworks/EPD64.framework/Versions/7.3/lib/python2.7/site-packages/IPython/core/interactiveshell.py', 2827, 'run_ast_nodes', ['if self.run_code(code):\n'], 0)
(<frame object at 0x10263eda0>, '/Library/Frameworks/EPD64.framework/Versions/7.3/lib/python2.7/site-packages/IPython/core/interactiveshell.py', 2741, 'run_cell', ['interactivity=interactivity, compiler=compiler)\n'], 0)
(<frame object at 0x10263e7c0>, '/Library/Frameworks/EPD64.framework/Versions/7.3/lib/python2.7/site-packages/IPython/core/interactiveshell.py', 2604, 'safe_execfile_ipy', ['self.run_cell(cell, silent=True, shell_futures=False)\n'], 0)