web-dev-qa-db-ja.com

Python-なぜ__init__.pyなしでモジュールをインポートできるのですか?

Python=は初めてですが、モジュールをインポートするために__init__.pyファイルが必要な理由を理解できません。他にも次のような質問と回答をしました。 これ

私を混乱させるのは、モジュールをインポートできるということですなし__init__py、それでなぜそれが必要なのですかまったく

私の例、

index.py
   modules/
      hello/
          hello.py
          HelloWorld.py

index.py、

import os
import sys

root = os.path.dirname(__file__)
sys.path.append(root + "/modules/hello")

# IMPORTS MODULES
from hello import hello
from HelloWorld import HelloWorld

def application(environ, start_response):

    results = []

    results.append(hello())

    helloWorld = HelloWorld()
    results.append(helloWorld.sayHello())

    output = "<br/>".join(results)

    response_body = output

    status = '200 OK'

    response_headers = [('Content-Type', 'text/html'),
                       ('Content-Length', str(len(response_body)))]

    start_response(status, response_headers)

    return [response_body]

modules/hello/hello.py、

def hello():
    return 'Hello World from hello.py!'

modules/hello/HelloWorld.py、

# define a class
class HelloWorld:
    def __init__(self):
        self.message = 'Hello World from HelloWorld.py!'

    def sayHello(self):
        return self.message

結果、

Hello World from hello.py!
Hello World from HelloWorld.py!

必要なのは、この2行だけです。

root = os.path.dirname(__file__)
sys.path.append(root + "/modules/hello")

__init__pyなし。なぜそれがこのように機能するのか誰かが説明できますか?

__init__pyが適切な方法である場合、コードで何を行う/変更する必要がありますか?

23
laukok

これは良いと思います 'answer' 私が理解していなかったことに対して。

myMath/
    __init__.py
    adv/
        __init__.py
        sqrt.py
        fib.py
    add.py
    subtract.py
    multiply.py
    divide.py

myMath/__ init __。py

from add import add
from divide import division
from multiply import multiply
from subtract import subtract
from adv.fib import fibonacci
from adv.sqrt import squareroot

index.py

import sys

sys.path.append('C:\Users\mdriscoll\Documents')

import mymath

print mymath.add(4,5)
print mymath.division(4, 2)
print mymath.multiply(10, 5)
print mymath.fibonacci(8)
print mymath.squareroot(48)
2
laukok

__init__.pypackages用です。パッケージには、関連するモジュールのコレクションが含まれています。使用したいモジュールが1つしかない場合は、__init__.pyを使用する必要はありません。単一の.pyファイルをシステムパスのどこかに置くだけで、インポートできます。

パッケージの目的は、パッケージ内のモジュールをインポートできるようにすることだけではありません。モジュールをグループ化することです。これの主な利点は、モジュールがパッケージ内にある場合、そのモジュールは相対インポートを使用してパッケージから他のモジュールをインポートできることです。同じパッケージにfoo.pybar.pyがある場合、foofrom . import barを実行できます。これにより、パッケージ内のインポートがよりコンパクトになり、パッケージを再構成したり名前を変更したりする場合に再編成が容易になります。

また、明らかな利点があります。 。 。それをパッケージにした場合、何かをインポートするたびにsys.pathを実行する必要はありません。

13
BrenBarn

これはPython使用しているバージョンが原因である可能性があります。実験を行ったところ、次のような構造になっていることがわかりました。

jedrzej@jedrzej-UX303LB ~/temp $ tree .
.
├── main.py
└── packages
    ├── file.py
    └── file.pyc

1 directory, 5 files

main.pyの内容:

import packages.file as p
p.fun()

およびfile.pyの内容:

import sys
def fun():
  print(sys.path)

Python= 2.7.12でmain.pyを実行しているとき、main.pyをPython 3.5.2で実行すると、ImportErrorが表示されます。 。

パッケージディレクトリに__init__.pyを追加すると、コードは両方のバージョンのPythonで動作します。

8
jedruniu

this リンクに基づく:Python 3.3以降

暗黙的な名前空間パッケージを許可するということは、__init__.pyファイルは完全に削除できます

6
Anton Zobnin

__init__.pyという名前のファイルは、ディスク上のディレクトリをPythonパッケージディレクトリとしてマークするために使用されます。ファイルがある場合

modules/spam/__init__.py
modules/spam/module.py

modulesがパスに含まれている場合、module.pyのコードを次のようにインポートできます

import spam.module

または

from spam import module

__init__.pyファイルを削除すると、Pythonはそのディレクトリ内のサブモジュールを検索しなくなるため、モジュールのインポートは失敗します。

__init__.pyファイルは通常は空ですが、パッケージの選択した部分をより便利な名前でエクスポートしたり、便利な関数を保持したりするために使用できます。上記の例を考えると、initモジュールの内容には次のようにアクセスできます。

import spam

そして最後に、公式ドキュメントがこのファイルについて述べなければならないものは次のとおりです。

__init__.pyファイルは、Pythonディレクトリをパッケージを含むものとして扱うために必要です。これは、文字列などの一般的な名前のディレクトリが誤って非表示になるのを防ぐために行われますモジュール検索パスで後で発生する有効なモジュール。最も単純なケースでは、__init__.pyは空のファイルでもかまいませんが、パッケージの初期化コードを実行したり、後で説明する__all__変数を設定したりすることもできます。 。

3
Shawn Mehan