条件が揃うと、以下のようなstacktraceが表示されて混乱が生じる。 print('yeah')の行でZeroDivisionErrorが発生しているように見えて困る。

>>> foo.foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/path/to/foo.py", line 3, in foo
    bar.bar()
  File "/path/to/bar.py", line 2, in bar
    print('yeah')
ZeroDivisionError: division by zero

友人が踏んで、私も見てみてしばらく分からなかった。 ちょっと面白かったので書いた。

再現

$ cat foo.py
import bar
def foo():
    bar.bar()
$ cat bar.py
def bar():
    0/0
$ python --version
Python 3.5.0
$ python
>>> import foo
>>> foo.foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/path/to/foo.py", line 3, in foo
    bar.bar()
  File "/path/to/bar.py", line 2, in bar
    0/0
ZeroDivisionError: division by zero
>>> ^Z
$ vim bar.py
$ cat bar.py
def bar():
    0/0
    print('yeah')
$ fg
>>> foo.foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/path/to/foo.py", line 3, in foo
    bar.bar()
  File "/path/to/bar.py", line 2, in bar
    print('yeah')
ZeroDivisionError: division by zero

  • 混乱を招くかもしれないが、まあ仕様の範疇だろう。
  • imp.reload(bar)としてbarmoduleを読み込み直せば解消される。import barimp.reload(foo)ではだめなことに注意。
  • 2でも3でも発生する。
  • rubyでは、そもそも行の内容が表示されないので発生しなかった。
irb(main):008:0> foo()
ZeroDivisionError: divided by 0
        from /path/to/bar.rb:2:in `/'
        from /path/to/bar.rb:2:in `bar'
        from /path/to/foo.rb:3:in `foo'
        from (irb):8
        from /usr/bin/irb:11:in `<main>'