Импорт пакетов в Python - PullRequest
       6

Импорт пакетов в Python

62 голосов
/ 29 января 2012

Я, вероятно, упускаю что-то очевидное, но в любом случае:

Когда вы импортируете пакет типа os в python, вы можете использовать любые субмодули / подпакеты вне очереди. Например это работает:

>>> import os
>>> os.path.abspath(...)

Однако у меня есть свой пакет, который структурирован следующим образом:

FooPackage/
  __init__.py
  foo.py

и тут та же логика не работает:

>>> import FooPackage
>>> FooPackage.foo
AttributeError: 'module' object has no attribute 'foo'

Что я делаю не так?

Ответы [ 5 ]

63 голосов
/ 29 января 2012

Когда вы импортируете FooPackage, Python просматривает каталоги в PYTHONPATH, пока не найдет файл с именем FooPackage.py или каталог с именем FooPackage, содержащий файл с именем __init__.py.Однако, найдя каталог пакета, он не затем сканирует этот каталог и автоматически импортирует все файлы .py.

Существует две причины такого поведения.Во-первых, при импорте модуля выполняется код Python, который может занимать время, память или иметь побочные эффекты.Поэтому вы можете импортировать a.b.c.d без необходимости импорта всего огромного пакета a.Проектировщик пакетов должен решить, будет ли __init__.py явно импортировать свои модули и подпакеты так, чтобы они были всегда доступны, или же клиентская программа сможет или не будет выбирать и загружать то, что загружено.

второй немного более тонкий, а также шоу-стоппер.Без явного оператора import (либо в FooPackage/__init__.py, либо в клиентской программе) Python не обязательно знает, какое имя он должен импортировать foo.py.В файловой системе без учета регистра (например, используемой в Windows) это может быть модуль с именами foo, Foo, FOO, fOo, foO, FoO, FOo или fOO.Все это допустимые отличные идентификаторы Python, поэтому Python просто не хватает информации из одного файла, чтобы понять, что вы имеете в виду.Следовательно, для того, чтобы вести себя согласованно во всех системах, требуется явное выражение импорта где-то для уточнения имени, даже в файловых системах, где доступна полная информация о регистре.

37 голосов
/ 29 января 2012

Вам необходимо импортировать подмодуль:

import FooPackage.foo

То, что вы делаете, ищет foo в FooPackage/__init__.py. Вы можете решить это, поставив import FooPackage.foo as foo (или from . import foo) в FooPackage/__init__.py, тогда Python сможет найти там foo. Но я рекомендую использовать мое первое предложение.

11 голосов
/ 13 августа 2013

Вам необходимо добавить from . import foo к файлу __init__.py в вашем пакете.

6 голосов
/ 02 марта 2018

Есть несколько важных заблуждений, которые необходимо устранить, особенно с помощью терминологии.Во-первых, обычно, когда вы думаете, что импортируете package в python, вы фактически импортируете module.Вы должны использовать термин package, когда вы думаете о терминах подструктуры файловой системы, которая помогает вам организовать ваш код.Но с точки зрения кода, всякий раз, когда вы импортируете package, Python рассматривает его как модуль.Все пакеты являются модулями.Не все модули являются пакетами.Модуль с атрибутом __path__ считается пакетом.

Вы можете проверить, что os является модулем.Чтобы подтвердить это, вы можете сделать:

import os
print(type(os)) # will print: <type 'module'>

В вашем примере, когда вы делаете import FooPackage, FooPackage обрабатывается и считается также модулем, и его атрибутами (функциями, классами и т. Д.).) предположительно определены в __init__.py.Поскольку ваш __init__.py пуст, он не может найти foo.

Вне операторов import вы не можете использовать запись '.' для адресации модулей внутри модулей.Единственное исключение происходит, если module импортируется в файл пакета предполагаемого родителя __init__.py.Чтобы прояснить ситуацию, давайте сделаем несколько примеров:

Рассмотрим исходную структуру:

FooPackage/
  __init__.py
  foo.py

Случай 1: __init__.py - пустой файл

#FooPackage imported as a module
import FooPackage 

#foo is not a name defined in `__init__.py`. Error
FooPackage.foo 

#FooPackage.foo imported as a module
import FooPackage.foo

#Error, foo has not been imported. To be able to use foo like this,
#you need to do: import FooPackage.foo as foo
foo.anything

#Not error, if anything is defined inside foo.py
FooPackage.foo.anything

Случай 2: в __init__.py есть строка import foo:

import FooPackage

#Now this is good. `foo` is sort of considered to be an attribute of 
#FooPackage
FooPackage.foo

Теперь предположим, что foo больше не является module, аfunction, который вы определили в __init__.py.если вы сделаете import FooPackage.foo, появится сообщение о том, что foo не является модулем.

0 голосов
/ 11 июля 2017

Вы можете импортировать пакет из библиотеки, используя оператор импорта.

синтаксис: импорт имя_модуля

     ex: import math

Вы можете импортировать только определенный метод из пакета, используя синтаксис blow

синтаксис: из имени_модуля имя_функции импорта

     ex: from math import radians
...