2014-02-11 5 views
2

Я собираюсь реорганизовать большой кусок моего кода на Python в виде пакета. Я полагаю, что этот пакет будет храниться в том же каталоге, где находится основной код. Таким образом, вся структура выглядит следующим образом:проблема с импортом локального пакета

project directory 
\-mymod 
    \-__init__.py # totaly empty 
    \-xsum.py  # with xsum function 
\-main.py  # main program 

Потому что это просто пример

#xsum.py 
def xsum(a,b): 
    "just xsum" 
    return a+b 

А внутри main.py:

#main.py 
import mymod 
print mymod.xsum.xsum(2,3) 

Python возвращает ошибку:

Traceback (most recent call last): 
    File "main.py", line 3, in <module> 
    print mymod.xsum.xsum(2,3) 
AttributeError: 'module' object has no attribute 'xsum' 

Я попытался добавить p roject и/или каталог проекта/mymod на sys.path, но это не помогает.

+3

'import mymod.xsum' вместо' import mymod' в main.py. Или 'from mymod import xsum' в ____init____.py, и вы можете просто« импортировать mymod »в main.py. – michaelmeyer

+0

@doukremt, вы правы, это работает. Но это очень странно. В документации нет ничего подобного. Почему я должен напрямую импортировать модуль в '__init __. Py'? – rth

+1

Я предполагаю, что это так, чтобы предотвратить конфликты имен. Например, у вас может быть функция 'xsum' в' __init __. Py', а затем, как определить, ссылается ли на это имя 'mymodule.xsum' на эту функцию, или вместо этого на файл' xsum.py'? Следует иметь в виду, что когда вы вводите 'import mymodule', то, что действительно импортирует Python, является набор имен, определенных в' mymodule/__ init __. Py'. Таким образом, чтобы держать вещи однозначными, удобно импортировать все файлы модулей в файл '__init __. Py' самого модуля. Таким образом, как «import mymod», так и «import mymod.xsum» остаются в силе. – michaelmeyer

ответ

2

Благодаря @doukremt (см обсуждения выше) я нашел очень простое решение: в __init__.py вставить код

import sys,os 
for filename in os.listdir(os.path.dirname(__file__)): 
     if filename[-3:] != ".py" or filename == "__init__.py" : continue 
     exec "from "+filename[:-3]+" import *" 

позволяет импортировать все имена из всех файлов в р текущего пакета в имени пакета пространства. Так использование довольно просто:

import mymod 
mymod.xsum(2,3) 

, если вы хотели бы отдельные модули имен в разных пространствах имен используйте следующий код в __init__.py: импорт SYS, OS

for filename in os.listdir(os.path.dirname(__file__)): 
     if filename[-3:] != ".py" or filename == "__init__.py" : continue 
     exec "import "+filename[:-3] 

В этом случае следует указать подмодуль:

import mymod 
mymod.xsum.xsum(2,3) 

Наконец, если вы хотели бы импортировать только несколько файлов в директории, составьте список и импортировать их:

import sys,os 
__all__=["a","b","c","xsum"] 
for filename in __all__: 
     exec "import "+filename 
Смежные вопросы