milk_spoonのブログ

さじの情報科学的活動、考えたこと、その他を雑記するためのブログです。

cannot import name …

pythonでdpktというパケット解析ライブラリを利用しようとして、pipでinstallもした、とりあえずテスト用ソースをコピペった、さあ動かすぞという段になってこのザマでした。
ちなみにバージョンはpython2.7.6 + dpkt1.8.6.2です。

$ python test.py 
Traceback (most recent call last):
  File "test.py", line 6, in <module>
    import dpkt
  File "/usr/local/lib/python2.7/dist-packages/dpkt/__init__.py", line 12, in <module>
    import aoe
  File "/usr/local/lib/python2.7/dist-packages/dpkt/aoe.py", line 6, in <module>
    from decorators import deprecated
  File "/usr/local/lib/python2.7/dist-packages/dpkt/decorators.py", line 4, in <module>
    from test import pystone
ImportError: cannot import name pystone

うわ。

pythonのバージョンが悪いのか、パッケージが実はうまくインストールできてないのか、とか色々考えましたが、testパッケージおよびpystoneはpython2.7ではインストール時にデフォルトであるという話もあり、しばらく原因が特定できず困っていました。

結論を言うと、以下のようにソース名を"test.py"から変更したところ動作しました。

$ mv test.py ttt.py
$ rm test.pyc 
$ python ttt.py 
(1, u'. time: ', 1303496629.238845, u'Length:', 60)
(2, u'. time: ', 1303496629.609845, u'Length:', 58)
...

一度実行してしまっている場合は.pycファイルも削除しなければいけないようです。

どうしてファイル名なんかで実行の成否が変わったのか…
これはpythonのimportの記法と優先関係にあるみたいです。kannokanno.hatenablog.com
最初のエラーメッセージでは結局何がエラーとなったかというと、

    from test import pystone
ImportError: cannot import name pystone

testパッケージのpystoneモジュールを読み込もうとしたけどそんなものはない!という点ですね。
そしてインポート対象ファイルの優先順位が

  1. 実行中のファイルと同じフォルダ
  2. カレントフォルダ
  3. 環境変数「PYTHONPATH」に列挙したフォルダ
  4. sys.pathに登録してあるフォルダ

…ありますね、カレントフォルダに"test"という名前のソースが…

つまり、本来4番目の「sys.pathに登録してあるフォルダ」の中の"test"(ディレクトリ)を探索してほしいところなのに、優先順位2番目のカレントディレクトリの"test"(.py)に先に引っかかってしまい、当然その"test"(.py)下にpystoneが存在するはずもなくエラーです!、という…

相当時間かかったので、原因がわかった時はかなり脱力しちゃいました。
こんなので動かなくなっちゃうのは正直やめてほしい。と思ったり思わなかったり。
しかも名前の衝突なので、pystoneやtestパッケージなど、限定的なキーワードで原因を調べても同様の事例がなくて焦りました。
こうして書いておくことで未来の自分や後に続く人が同じ轍を踏んで時間を浪費することのないよう祈るばかりです。