既にフラットパッケージを使用しているので、ネストされたパッケージで発生する問題を予期していませんでした。ここは…
dir
|
+-- test.py
|
+-- package
|
+-- __init__.py
|
+-- subpackage
|
+-- __init__.py
|
+-- module.py
package/__init__.py
とpackage/subpackage/__init__.py
の両方が空です。
module.py
のコンテンツ# file `package/subpackage/module.py`
attribute1 = "value 1"
attribute2 = "value 2"
attribute3 = "value 3"
# and as many more as you want...
test.py
のコンテンツ(3バージョン)# file test.py
from package.subpackage.module import *
print attribute1 # OK
これは、物をインポートするための悪い安全な方法です(すべてを一括でインポートします)が、機能します。
# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
from module import attribute1
アイテムごとにインポートするより安全な方法ですが、失敗します。Pythonこれは望ましくありません:「モジュールという名前のモジュールはありません」というメッセージが表示されて失敗します。しかしながら …
# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
print module # Surprise here
…<module 'package.subpackage.module' from '...'>
。それはモジュールですが、それはモジュールではありません/ -P 8-O ... uh
# file test.py v3
from package.subpackage.module import attribute1
print attribute1 # OK
これは動作します。したがって、常にオーバーキルプレフィックスを使用するか、バージョン#1のように安全でない方法を使用し、Pythonによって許可されて安全な便利な方法を使用する必要がありますか? Pythonが拒否する唯一の方法は、安全で不要な長いプレフィックスを避けるより良い方法ですか?これはimport *
が好きなのか、それとも長すぎる接頭辞が好きなのか(この慣行の実施に役立たない)?.
難しい言葉で申し訳ありませんが、この2日間はこの愚かな行動を回避しようとしています。どこかで完全に間違っていなければ、これはPythonのパッケージとサブパッケージのモデルで何かが本当に壊れていると感じさせるでしょう。
ノート
sys.path
に依存したり、同じグローバルな効果で*.pth
で遊ぶための別の方法であるsys.path
ファイルに依存したくありません。ソリューションをクリーンにするためには、ローカルのみにする必要があります。 Pythonはサブパッケージを処理できますが、そうでない場合もありますが、ローカルなものを処理できるようにするためにグローバル構成を操作する必要はありません。package/subpackage/__init__.py
でインポートを使用しようとしましたが、何も解決せず、同じことを行い、subpackage
は既知のモジュールではないと文句を言いますが、print subpackage
はそれがモジュールであると言います)。私は完全に間違っているかもしれません(私が好むオプション)が、これは私がPythonについて多くの失望を感じさせます。
私が試した3つ以外の既知の方法はありますか?私が知らない何か?
(はぁ)
-----%<-----編集----->%-----
すべてのパッケージ参照はグローバルディクショナリにのみ移動するため、Pythonには実際のサブパッケージのようなものはありません。これは、ローカル辞書がないことを意味し、ローカルパッケージ参照を管理する方法がないことを意味します。
完全なプレフィックスまたは短いプレフィックスまたはエイリアスを使用する必要があります。次のように:
from package.subpackage.module import attribute1
# An repeat it again an again
# But after that, you can simply:
use_of (attribute1)
from package.subpackage import module
# Short but then you have to do:
use_of (module.attribute1)
# and repeat the prefix at every use place
または、上記のバリエーション。
from package.subpackage import module as m
use_of (m.attribute1)
# `m` is a shorter prefix, but you could as well
# define a more meaningful name after the context
一度に複数のエンティティを一度にインポートすることを気にしない場合は、次のことができます。
from package.subpackage.module import attribute1, attribute2
# and etc.
私の最初の好みではありませんが(インポートされたエンティティごとに1つのインポートステートメントを持っていることを好みます)、個人的に好むものかもしれません。
更新(2012-09-14):
最後に、レイアウトに関するコメントを除いて、実際には問題ないように見えます。上記の代わりに、私は使用しました:
from package.subpackage.module import (
attribute1,
attribute2,
attribute3,
...) # and etc.
import
がモジュールを検索する方法を誤解しているようです。 importステートメントを使用すると、alwaysは実際のモジュールパス(および/またはsys.modules
)を検索します。以前のインポートのために存在するローカル名前空間のモジュールobjectsを使用しません。行うとき:
import package.subpackage.module
from package.subpackage import module
from module import attribute1
2行目はpackage.subpackage
というパッケージを探し、そのパッケージからmodule
をインポートします。この行は、3番目の行には影響しません。 3行目はmodule
というモジュールを探しているだけで、見つかりません。上記の行から取得したmodule
というオブジェクトを「再利用」しません。
言い換えれば、from someModule import ...
は「先ほどインポートしたsomeModuleというモジュールから...」という意味ではなく、「sys.pathで見つかるsomeModuleという名前のモジュールから」という意味です。モジュールにつながるパッケージをインポートして、モジュールのパスを「インクリメンタルに」構築する方法はありません。インポート時には常にモジュール名全体を参照する必要があります。
何を達成しようとしているのか明確ではありません。特定のオブジェクトattribute1のみをインポートする場合は、from package.subpackage.module import attribute1
を実行して完了です。必要な名前をインポートしたら、長いpackage.subpackage.module
について心配する必要はありません。
do後で他の名前にアクセスするためにモジュールにアクセスしたい場合は、from package.subpackage import module
を実行できます。これまで見てきたように、module.attribute1
などを実行できます好きなだけ。
both ---が必要な場合、つまりattribute1
に直接アクセス可能にする場合andmodule
にアクセス可能にする場合は、上記の両方を実行します:
from package.subpackage import module
from package.subpackage.module import attribute1
attribute1 # works
module.someOtherAttribute # also works
package.subpackage
を2回入力するのが嫌な場合は、attribute1へのローカル参照を手動で作成できます。
from package.subpackage import module
attribute1 = module.attribute1
attribute1 # works
module.someOtherAttribute #also works
#2が失敗する理由は、sys.modules['module']
が存在せず(インポートルーチンに独自のスコープがあり、module
ローカル名を表示できないため)、module
モジュールまたはパッケージが存在しないためです。ディスク。インポートされた複数の名前をコンマで区切ることができることに注意してください。
from package.subpackage.module import attribute1, attribute2, attribute3
また:
from package.subpackage import module
print module.attribute1
グローバルネームスペースでattribute1を取得することだけが目的であれば、バージョン3は問題ありません。なぜそれはプレフィックスを過剰殺すのですか?
バージョン2では、代わりに
from module import attribute1
できるよ
attribute1 = module.attribute1