Невозможно импортировать Python из другой папки

Я не могу заставить 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.