Python では、プログラムでモジュールをインポートする場合は、次のようにします。
module = __import__('module_name')
サブモジュールをインポートしたい場合、次のようにすれば簡単にできると思います。
module = __import__('module_name.submodule')
もちろん、これは機能しません。module_name
もう一度取得するだけです。次の操作を行う必要があります。
module = __import__('module_name.submodule', fromlist=['blah'])
なぜ?の実際の値はfromlist
、空でない限り、まったく問題にならないようです。引数を要求して、その値を無視することにはどのような意味があるのでしょうか?
Python のほとんどの処理は正当な理由があって行われているようですが、この動作が存在する理由について、私にはどうしても合理的な説明が思いつきません。
ベストアンサー1
実際、 の振る舞いは、を呼び出すステートメント__import__()
の実装に完全に起因します。 は基本的に、によって呼び出される5 つのわずかに異なる方法(2 つの主なカテゴリ) があります。import
__import__()
__import__()
import
import pkg
import pkg.mod
from pkg import mod, mod2
from pkg.mod import func, func2
from pkg.mod import submod
最初にそして2 番目のケースでは、import
ステートメントは「最も左の」モジュール オブジェクトを「最も左の」名前 に割り当てる必要があります。pkg
ステートメントによってローカル名 が導入されたため、属性を持つモジュール オブジェクトをimport pkg.mod
実行できます。したがって、関数は「最も左の」モジュール オブジェクトを返して、 に割り当てる必要があります。したがって、これら 2 つのインポート ステートメントは次のように変換されます。pkg.mod.func()
import
pkg
mod
__import__()
pkg
pkg = __import__('pkg')
pkg = __import__('pkg.mod')
3 番目、4 番目、および 5 番目のケースでは、import
ステートメントはより多くの作業を行う必要があります。つまり、(潜在的に) 複数の名前を割り当てる必要があり、その__import__()
名前はモジュール オブジェクトから取得する必要があります。関数は 1 つのオブジェクトのみを返すことができ、モジュール オブジェクトからそれらの名前をそれぞれ取得させる理由はありません (また、実装がはるかに複雑になります)。したがって、単純なアプローチは次のようになります (3 番目のケースの場合)。
tmp = __import__('pkg')
mod = tmp.mod
mod2 = tmp.mod2
pkg
ただし、がパッケージであり、mod
またはmod2
そのパッケージ内のモジュールである場合は機能しません。まだ輸入されていないもの3 番目と 5 番目のケースと同様に、関数はとがステートメントでアクセス可能な名前である__import__()
ことを知っておく必要があります。そうすることで、関数はそれらがモジュールであるかどうかを確認し、それらもインポートしようとすることができます。そのため、呼び出しは次のようになります。mod
mod2
import
tmp = __import__('pkg', fromlist=['mod', 'mod2'])
mod = tmp.mod
mod2 = tmp.mod2
これにより、 はおよび との__import__()
ロードを試行します(ただし、またはが存在しない場合は、呼び出しでエラーにはなりません。エラーの生成はステートメントに委ねられます)。ただし、これは 4 番目と 5 番目の例には依然として適切ではありません。呼び出しが次のようになると、pkg.mod
pkg.mod2
pkg
mod
mod2
__import__()
import
tmp = __import__('pkg.mod', fromlist=['submod'])
submod = tmp.submod
すると、以前と同じように になり、属性を取得したいモジュールではなくtmp
なります。実装では、関数が既に行っているようにパッケージ名を に分割して名前を走査するなど、ステートメントが余分な作業を行うようにすることもできましたが、これは労力の一部を重複させることを意味していました。そのため、代わりに実装ではを返すようにしました。pkg
pkg.mod
submod
import
.
__import__()
__import__()
一番右モジュールの代わりに左端1つもし、もし、fromlist が渡され、空ではありません。
( およびimport pkg as p
構文from pkg import mod as m
は、どのローカル名が割り当てられるかを除いて、このストーリーについては何も変更しません。が使用され__import__()
ても関数は何も変更せずas
、すべてimport
ステートメントの実装に残ります。)