4

編集:OK、私はバグとそれを再現するための正確で完全なコードを分離することができました。しかし、それは仕様によるものか、Pythonのバグのいずれかであるように見えます。

もちろん、 2つの兄弟パッケージを作成します。 adminGeneral、それぞれに独自のパッケージがあります__init__.py。パッケージadminに、次のコードを含むファイル'test.py'を配置します。

from General.test02 import run
import RunStoppedException
try:
    run()
except RunStoppedException.RunStoppedException,e:
    print 'right'
except Exception,e:
    print 'this is what i got: %s'%type(e)

またadmin、次のコードを使用してファイル'RunStoppedException.py'を配置します。

class RunStoppedException(Exception):
    def __init__(self):
        Exception.__init__(self)

パッケージGeneralに、次のコードを含むtest02.pyファイルを入れます。

import admin.RunStoppedException
def run():
    raise admin.RunStoppedException.RunStoppedException()

印刷物:

this is what i got: <class 'admin.RunStoppedException.RunStoppedException'>

あるべきだったときright。これは、1つのファイルが例外と同じディレクトリにある場合にのみ発生するため、インポート方法が異なります。

これは仕様によるものですか、それともPythonのバグですか?

私はpython2.6を使用しており、eclipse+pydevで実行しています。

4

3 に答える 3

7
import admin.RunStoppedException

これはあいまいな相対インポートです。トップレベルのモジュールRunStoppedExceptionからですか?adminまたはmypackage.adminあなたがパッケージに入っているときから?現在の作業ディレクトリ(モジュール検索パスに追加されている)がパッケージ内にある場合は、Pythonがパッケージ内にあることを認識しているかどうかに応じて、スクリプトの実行方法に応じて、どちらかになります。

両方import admin.RunStoppedExceptionimport RunStoppedException異なるモジュールがある場合、同じモジュールの2つのコピー(パッケージのトップレベルRunStoppedExceptionとサブモジュール)をインポートすると、例外が2つ発生し、その後に不一致が発生する可能性があります。admin.RunStoppedExceptionadminexcept

したがって、暗黙的な相対インポートは使用しないでください。それらはいずれにせよなくなります(PEP328を参照)。常に完全なモジュール名を綴ります。例:import mypackage.admin.RunStoppedException。ただし、これはひどく混乱するため、モジュール名とクラス名に同じ識別子を使用することは避けてください。Pythonでは次のように言うことができることに注意してください。

except RunStoppedException:

ここで、その識別子は、例外のサブクラスではなく、モジュールを参照しています。これは歴史的な理由によるものであり、なくなる可能性もありますが、当面の間はバグを隠すことができます。一般的なパターンは、mypackage.exceptions多くの例外を保持するために使用することです。ファイルごとに1つのクラスは、Pythonで嫌われているJavaの習慣です。

また、一般的に、モジュールの内容(クラスなど)のインポートを可能な限り抑えるようにすることもお勧めします。モジュール内のコピーが変更された場合RunStoppedException、スクリプトごとに異なるコピーが作成されます。クラスはほとんど変更されませんが、モジュールレベルの変数は変更される可能性があり、所有者モジュールの外部にあるものを取得する場合、モンキーパッチとリロードははるかに困難になります。

于 2010-01-01T13:53:32.447 に答える
0

私にとってはうまくいきます:

[/tmp] ls admin/
RunStoppedException.py  __init__.py     test.py
RunStoppedException.pyc __init__.pyc
[/tmp] ls General/
__init__.py __init__.pyc    test02.py   test02.pyc
[/tmp] python -m admin.test 
right
[/tmp] 

実行中:

Python 2.6.4 Stackless 3.1b3 060516 (release26-maint, Dec 14 2009, 23:28:06) 
[GCC 4.2.1 (Apple Inc. build 5646) (dot 1)] on darwin

私の推測では、おそらく以前のテストから、どこかに別の「一般」があり、それが例外が一致しない理由です。id/inspect.getabsfileデバッグを試しましたか?もしそうなら、出力は何でしたか?

于 2010-01-01T13:45:11.873 に答える
0

私は2つの理由しか見ることができません

  1. 同じ名前の2つの異なる例外クラスがあります
    編集:例外クラスを2つの方法でインポートするため、原因はこの部分だと思います

    • RunStoppedExceptionからインポートRunStoppedException
    • admin.RunStoppedExceptionからインポートRunStoppedException

    それらを一貫させると、問題はなくなります。

  2. コードに干渉しているIDEを使用しています。これは奇妙に聞こえますが、そうでない場合はコマンドラインでコードを実行してみてください。

1と2でも問題が解決しない場合は、問題を示す小さなコードを記述します。ここで実行でき、修正できますが、このような小さなスタンドアロンを記述したら、修正する必要はないと確信しています。問題を再現できるスクリプトで、解決策も見つかります。

于 2010-01-01T13:09:51.217 に答える