2016-09-07 1 views
3

У меня есть следующая структура каталогов:Импортирующие модули, используемые в пакете в __init__.py

funniest/ 
    setup.py 
    funniest/ 
      __init__.py 
      ModuleA.py 
      ModuleB.py 
# __init__.py 
from numba import jit 

from .ModuleA import ClassA 
# ModuleA.py 
import funniest.ModuleB 

class ClassA(): 
    pass 
# ModuleB.py 
@jit 
def f(): 
    pass 

Однако при импорте модуля I получите сообщение об ошибке:

>>> import funniest 
Traceback (most recent call last): 
File "<stdin>", line 1, in <module> 
File "/home/domi89/Dropbox/Python_Projects/funniest/funniest /__init__.py", line 2, in <module> 
from .ModuleA import ClassA 
File "/home/domi89/Dropbox/Python_Projects/funniest/funniest /ModuleA.py", line 1, in <module> 
import funniest.ModuleB 
File "/home/domi89/Dropbox/Python_Projects/funniest/funniest/ModuleB.py", line 1, in <module> 
@jit 
NameError: name 'jit' is not defined 

Я не могу понять, почему это происходит, потому что когда __init__.py выполнить сначала, первое, что он делает, это импорт from numba import jit. Так почему же jit не определено, когда дело доходит до функции f в ModuleB?

+2

Вам нужно импортировать вещи, которые вы используете * в B *, а не только на уровне модуля. – jonrsharpe

ответ

3

Название jit не известно внутри ModuleB. Импорт Python не работает, так как C/C++ включает в себя развертывание кода вместо import. Новый модуль создает новое пространство имен с картой внутри - карту с функциями, классами и т. Д.

Итак, когда вы сделали import funniest, вы создали новую запись в текущем пространстве имен, например: {..., funniest: {}, ...}. При импорте funniest вы импортировали jit и ClassA, поэтому с того места, где вы импортировали модуль funniest, у вас есть доступ к такой карте: funniest: {jit: {..}, ClassA: {...}}.

В ModuleA вы импортировали ModuleB, поэтому в ModuleA вы имеете новую переменную ModuleB:{...} с содержанием ModuleB. Но здесь вы не видите карту funniest - она ​​находится на другом уровне в иерархии.

И в ModuleB вы не видите funniest и ClassA карты (пространства имен - и все, что вы хотите называть это;)).

+0

Вы красиво сломались это вниз, спасибо. Таким образом, на самом деле не имеет смысла вставлять вложение в файл '__init __. Py', если я хочу, чтобы они использовались внутри пакета, не делая их доступными для пользователя, импортирующего пакет? – NoBackingDown

+1

Да, для внутреннего использования внутри пакета «импорт» в __init__.py не влияет. Но снаружи, как вы указали, - это очень полезно;) – Krzysiek

5

Импорт, который вы положили в funniest/__init__.py, импортируется только тогда, когда вы делаете import funniest, а не автоматически внутри подмодулей. Так ModuleB не знает о jit.

Что вам нужно сделать здесь, это переместить from numba import jit от __init__.py до ModuleB.py.

+1

Как правило, если я создаю пакет, состоящий из разных модулей, каждый отдельный модуль нуждается в собственных импортах в верхней части файла? Нет возможности импортировать материал один раз для всех модулей? – NoBackingDown

+0

@ Dominik: Точно. Модули являются отдельными пространствами имен. Как я уже сказал в комментарии к другому ответу (теперь удаленному), каждый модуль отвечает за импорт собственных зависимостей. Одним из распространенных автоматических тестов является «импорт имени», а затем выход для каждого файла _name_.py в вашем проекте --- они должны каждый импортировать чисто, даже если ничего больше не импортировано до или после. –

+1

@ Dominik - это интересный источник, чтобы получить четкое представление: https://docs.python.org/2/tutorial/modules.html – Krzysiek

Смежные вопросы