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]
модули/Привет/hello.py,
def hello():
return 'Hello World from hello.py!'
модули/Привет/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!
Что нужно, это просто эти две строки,
root = os.path.dirname(__file__)
sys.path.append(root + "/modules/hello")
Без __init__py
. Может кто-нибудь объяснить, почему он работает таким образом?
Если __init__py
является правильным способом, что мне делать/изменять в моем коде?
Ответы
Ответ 1
Я думаю, что это хороший 'answer' для того, что я не понял.
myMath/
__init__.py
adv/
__init__.py
sqrt.py
fib.py
add.py
subtract.py
multiply.py
divide.py
MyMath/__ __ INIT. Ру
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
__init__.py
для пакетов. Пакет содержит набор связанных модулей. Если у вас только один модуль, который вы хотите использовать, вам не нужно использовать __init__.py
; просто поместите одиночный файл .py
где-нибудь на системный путь, и вы можете его импортировать.
Цель пакетов - не только позволить вам импортировать модули внутри них. Он объединяет модули вместе. Главное преимущество этого заключается в том, что если модуль находится внутри пакета, то этот модуль может импортировать другие модули из пакета с использованием относительного импорта. Если у вас есть foo.py
и bar.py
в одном пакете, тогда foo
может просто сделать from . import bar
. Это делает импорт внутри пакета более компактным и проще реорганизовать, если вы реструктурируете пакет или измените его имя.
Кроме того, очевидное преимущество., если вы делаете это пакетом, вам не нужно делать это sys.path
каждый раз, когда вы хотите что-то импортировать из него.
Ответ 3
Я думаю, что это может быть связано с используемой версией Python. Я сделал несколько экспериментов и выяснил, что имеет следующую структуру:
[email protected] ~/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)
Когда я выполняю main.py
с Python 2.7.12, я получаю ImportError
, а выполнение main.py
с Python 3.5.2 просто работает.
После добавления __init__.py
в каталог пакетов код работает с обеими версиями Python.
Ответ 4
Файлы с именем __init__.py
используются для маркировки каталогов на диске в виде каталогов пакетов Python. Если у вас есть файлы
modules/hello/__init__.py
modules/hello/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__
, описанную ниже.
Ответ 5
На основе этой ссылки: с Python 3.3
Разрешение неявных пакетов пространства имен означает, что требование предоставить файл __init__.py
можно полностью отбросить