Я не могу заставить Python импортировать модуль во вложенную папку. Я получаю ошибку, когда пытаюсь создать экземпляр класса из импортированного модуля, но сам импорт успешно завершен. Вот моя структура каталогов:
Server
-server.py
-Models
--user.py
Здесь содержимое server.py:
from sys import path
from os import getcwd
path.append(getcwd() + "\\models") #Yes, i'm on windows
print path
import user
u=user.User() #error on this line
И user.py:
class User(Entity):
using_options(tablename='users')
username = Field(String(15))
password = Field(String(64))
email = Field(String(50))
status = Field(Integer)
created = Field(DateTime)
Ошибка:
AttributeError: объект 'module' не имеет атрибута 'User'
Ответ 1
Я считаю, что вам нужно создать файл с именем __init__.py
в каталоге Models, чтобы python рассматривал его как модуль.
Затем вы можете сделать:
from Models.user import User
Вы можете включить код в __init__.py
(например, код инициализации, который требуется нескольким различным классам) или оставить его пустым. Но он должен быть там.
Ответ 2
Вам нужно создать __init__.py
в подпапке Models
. Файл может быть пустым. Он определяет пакет.
Затем вы можете сделать:
from Models.user import User
Прочитайте все об этом в учебнике python, здесь.
Существует также хорошая статья об организации файлов проектов python здесь.
Ответ 3
импортировать пользователя
u = user.User() #error в этой строке
Из-за отсутствия __init__, упомянутого выше, вы ожидаете, что ImportError сделает проблему более ясной.
Вы не получите его, потому что "пользователь" также является существующим модулем в стандартной библиотеке. Оператор import захватывает его и пытается найти в нем класс User; который не существует, и только тогда вы получите ошибку.
Как правило, рекомендуется сделать ваш импорт абсолютным:
import Server.Models.user
чтобы избежать такой двусмысленности. Действительно, из Python 2.7 пользователь импорта не будет относиться к текущему модулю вообще.
Если вы действительно хотите относительный импорт, вы можете явно указать их в Python 2.5 и использовать несколько уродливый синтаксис:
from .user import User
Ответ 4
Правильный способ импорта модуля, расположенного в родительской папке, когда у вас нет стандартной структуры пакета, является:
import os, sys
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.dirname(CURRENT_DIR))
(вы можете объединить последние две строки, но этот способ легче понять).
Это решение является кросс-платформенным и достаточно общим, чтобы в других обстоятельствах не требовалось изменять.
Ответ 5
Вам не хватает __init__.py. Из учебника Python:
Файлы __init__.py необходимы для заставить Python рассматривать каталоги как содержащие пакеты; это делается для предотвращать каталоги с общим имя, например строка, из непреднамеренное скрытие действительных модулей которые появляются позже при поиске модуля дорожка. В простейшем случае, __init__.py может быть просто пустым файлом, но он также может выполнять инициализацию код для пакета или установить __all__, описанная ниже.
Поместите пустой файл с именем __init__.py в каталог моделей, и все должно быть золотым.
Ответ 6
как вы выписываете параметры os.path.dirname
.... команда?
import os, sys
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.dirname(CURRENT_DIR))
Ответ 7
Решение glarrain работает лучше всего. Я столкнулся с проблемой того, что Python не смог распознать мои модули python и дал мне ошибку "модуль не найден". Для меня, даже после добавления файлов __init__.py
и импорта модулей соответственно, я все равно получил ту же ошибку.
Я решил проблему, следуя гларренному ответу.
Ответ 8
Мой предпочтительный способ - иметь __init__.py в каждом каталоге, который содержит модули, которые используются другими модулями, и в точке входа переопределить sys.path, как показано ниже:
def get_path(ss):
return os.path.join(os.path.dirname(__file__), ss)
sys.path += [
get_path('Server'),
get_path('Models')
]
Это делает файлы в указанных каталога видимыми для импорта, и я могу импортировать пользователя из Server.py.
Ответ 9
Изучив ответы, предоставленные этими авторами выше - Zorglub29, Том, Марк, Аарон Макмиллин, lucasamaral, JoeyZhao, Кьелд Фларуп, Procyclinsur, martin.zaenker, tooty44 и отладив проблему, с которой я столкнулся, я обнаружил другой вариант использования, связанный с к которому я столкнулся с этой проблемой. Следовательно, добавив мои наблюдения ниже для кого-либо ссылки.
В моем коде у меня был циклический импорт классов. Например:
src
|-- utilities.py (has Utilities class that uses Event class)
|-- consume_utilities.py (has Event class that uses Utilities class)
|-- tests
|-- test_consume_utilities.py (executes test cases that involves Event class)
Я получил следующую ошибку, когда попытался выполнить python -m pytest tests/test_utilities.py для выполнения UT, написанных в test_utilities.py.
ImportError while importing test module '/Users/.../src/tests/test_utilities.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests/test_utilities.py:1: in <module>
from utilities import Utilities
...
...
E ImportError: cannot import name 'Utilities'
Способ устранения ошибки состоял в том, чтобы переформулировать мой код, чтобы переместить функциональность в класс циклического импорта, чтобы я мог удалить циклический импорт классов.
Обратите внимание, у меня есть файл __init__.py
в моей папке ' src ', а также папка ' tests ', и я все же смог избавиться от ' ImportError ', просто переформировав код.
Следующая ссылка на stackoverflow предоставляет гораздо больше подробностей о круговой зависимости в Python.