web-dev-qa-db-ja.com

Python module import-コンポーネントが明示的にインポートされた場合にのみ利用できるのはなぜですか?

最近scikit-imageバージョン0.11.3をインストールしました。 python 2.7.10を使用しています。モジュール全体をインポートすると、ioモジュールにアクセスできません。

import skimage
img = skimage.io.imread(path_)

エラーを与える:

AttributeError: 'module' object has no attribute 'io'

ただし、以下はエラーになりません。

from skimage import io
img = io.imread(path_)

質問:なぜですか?

14
jmsinusa

簡単な答え:IOはサブモジュールです。サブモジュールは親モジュールから明示的にインポートする必要があります。

長い答え:python docsのセクション5.4.2から:

何らかのメカニズム(例:importlib API、importまたはimport-fromステートメント、または組み込みimport())を使用してサブモジュールが読み込まれると、親モジュールの名前空間にサブモジュールオブジェクトへのバインディングが配置されます。たとえば、パッケージspamにサブモジュールfooがある場合、spam.fooをインポートした後、spamにはサブモジュールにバインドされた属性fooがあります。次のディレクトリ構造があるとします。

spam/
    __init__.py
    foo.py
    bar.py

そしてspam/init。pyには次の行があります:

from .foo import Foo
from .bar import Bar

次に、以下を実行すると、名前がfooとbarにバインドされてspamモジュールに入れられます。

>>>
>>> import spam
>>> spam.foo
<module 'spam.foo' from '/tmp/imports/spam/foo.py'>
>>> spam.bar
<module 'spam.bar' from '/tmp/imports/spam/bar.py'>

Pythonのなじみのある名前バインディングルールを考えると、これは意外に思われるかもしれませんが、実際にはインポートシステムの基本的な機能です。不変の保持は、sys.modules ['spam']とsys.modules ['spam.foo']がある場合(上記のインポート後のように)、後者は前者のfoo属性として表示される必要があるということです。

10
Shawn Mehan

それは単にPython=モジュールを処理する方法です。

1つの理由は、cpythonがサブモジュールをスキャンしてすべてをインポートしてから、すべてのサブモジュールをインポートする必要がある場合、1つのモジュールのインポートが非常に遅くなることです。

もう1つの理由は、「暗黙よりも明示的にする方がよい」です。 Python複雑なモジュール階層を持つパッケージのごく一部のみが必要な場合に、可能な限りすべてをインポートする必要があるのはなぜですか?.

の代わりに from skimage import io書くこともできます

import skimage.io

次に、skimage.io.imreadが見つかります。

7
cg909