Importing Python Modules


原文:
http://effbot.org/zone/import-confusion.htm
概要
importとfrom-inmportはPython初心者に対してしばしば深刻な混淆を持ってきますが、それらの実現メカニズムが分かったら、彼らを使うことに対していかなる困惑もないと信じています.
この文章はimportとfrom-mportに関するすべてを整理するように努力します.
import modulesのいくつかの方法
Pythonは、少なくとも3つの方法でimport modulesを提供する.import、fromまたは内蔵の_u uを使用します.import.function、紙面の制限する本文はその他の非主流の方式を討論しません.以下はこのいくつかの方法の実現原理である.

  • import Xはmodule Xを導入し、現在の名前空間でXへの参照を作成する.つまり、import Xは、モジュールXの中のものを使ってもいいです.

  • from X import*はmodule Xを導入し、現在の名前空間でX中のすべてのpublicオブジェクトに作成します.すなわち名前を除いて「*」で始まるすべてのオブジェクトです.の引用.つまり、この文を実行した後、直接に名前を使ってmodule Xのものを使うことができます.ただし、X自体は未定義ですので、X.nameは使えません.名前が重複している場合は、より新しいバージョンが使われます.Xの中でこの名前が他の対象に向けられていても、気づかないようになります.これもこの方法の危険な点です.使いやすいですが、意識しにくいです.間にバグが発生します

  • from X import a,b,cはmodule Xを導入し、現在の名前空間で所定のオブジェクトの参照を作成し、a,b,cを直接使用することができます.

  • X=u_import_u(X)はimport Xと似ていますが、1)stringを使ってmoduleの名前を伝えることができます.2)現在の名前空間で変数に割り当てられます.
  • どちらを採用すればいいですか?
    簡単に言えば、できるだけimportを使います.
    以下のいくつかの状況は例外です.

  • Module文書はfrom-mportを使用する必要があります.一般的な例はTkinterです.現在の名前空間にのみwidget clasesと関連する定数を追加するように設計されています.import Tkinterを使用するとコードの可読性が悪くなりますので、推奨されません.

  • パッケージの中のコンポーネントを導入します.パッケージの中の特定のサブmoduleを導入するだけで、from io.drivers import zipを使用する場合は、一般的にimport.drivers.zipより便利です.前者はzipで簡単にこのmoduleを使用できます.そのフルネームio.drivers.zipを使用するのではなく、このような場合はfromporimport-inpの方が簡単に機能します.名前が紛らわしいというリスクもない.

  • 実行前にmoduleの名前が分かりません.この場合はmodulemoduleの名前を変更する際にコードを変更する必要はありません.

  • 自分に何をするかはよく分かります.確認すればできるだけfrom importを使ってもいいですが、よく考えてから行きます.-)
  • Pythonはどうやってmoduleを導入しますか?
    Pythonがmoduleを導入すると、まずmoduleレジストリ(sys.modules)を確認し、moduleが既に導入されているかどうかを確認し、存在すれば導入されたmoduleを使って代替します.
    そうでなければ、Pythonは以下のステップを実行します.
  • は、新しい空moduleオブジェクトを作成します.
  • は、このmoduleオブジェクトをsys.modules dictionaryに挿入する
  • .
  • moduleのコードオブジェクトをロードする(必要であれば先にこのmoduleをコンパイルする)
  • 新しいmoduleの名前空間でこのmoduleのコードオブジェクトを実行します.コードに割り当てられたすべての変数はこのmoduleオブジェクトで利用できます.このmoduleオブジェクトを通じてExecute the module code object in the new module’s namespace.All variable.assigned by the code avavedule
    これはロードされたmoduleの性能消耗が非常に小さいという意味で、Pythonはdictionaryの中でmoduleの名前を検索すればいいです.
    その他のポイント
    シナリオとしてmoduleを使う
    もしあなたがシナリオとして動作すると、それを直接コンパイラではなくコンパイラに名前を付けます.後で同じmoduleをプログラムにロードすると、その実名で再ロードされます.注意しないと同じことが2回もできます.
    巡回インポート
    Pythonではdef、class、importなどの語句が声明です.
    moduleは導入時に実行されますが、新しい関数とクラスはmoduleの名前空間に追加されません.defまたはclassを実行して声明を出すまでは、循環導入に大きな影響があります.
    例えばmodule Xはmodule Yを導入して、関数spamを定義します.
        # module X
        import Y
        def spam():
            print "function in module x"
    メインプログラムからXを導入すると、PythonはXのコードをロードして実行します.Pythonからimport Yまでの声明の場合、YのコードをロードしてYのコードを実行します.
    この時、Pythonはすでにsys.modulesにXとYをロードしましたが、Xはまだ何も含まれていません.def spamはまだ実行されていません.
    現在、YがXを導入すると(循環導入が発生した)、空module Xオブジェクトへの参照が得られますが、関数X.spamを呼ぼうとしたら失敗します.Xは存在しますが、X.spamは存在しません.
        # module Y
        from X import spam # doesn't work: spam isn't defined yet!
    この問題はfrom-mportの使用に関係なく、importを使っても同じです.
        # module Y
        import X
        X.spam() # doesn't work either: spam isn't defined yet!
    解決の方法はコードの再構成であり、通常は部分コンテンツを個々のmoduleに分割して解決することができます.このような解決方法は、C++において循環参照を解決する際に前置宣言を使用して分離を宣言し、定義する方法で、競合する実行コードを他のファイルに分割します.
    或いはimportをmoduleの末尾に移動します.例えば上記の例ではimport Yをmodule Xの末尾に移動すれば正常です.しかし、あまり効果がないです.もしX.spamがYを使ったらまた間違います.