Не удается получить Python для импорта из другой папки - PullRequest
77 голосов
/ 19 января 2009

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

Ответы [ 8 ]

115 голосов
/ 19 января 2009

Я считаю, что вам нужно создать файл с именем __init__.py в каталоге Models, чтобы python рассматривал его как модуль.

Тогда вы можете сделать:

from Models.user import User

Вы можете включить код в __init__.py (например, код инициализации, который требуется нескольким различным классам) или оставить его пустым. Но это должно быть там.

20 голосов
/ 19 января 2009

Вы должны создать __init__.py в подпапке Models. Файл может быть пустым. Он определяет пакет.

Тогда вы можете сделать:

from Models.user import User

Прочитайте все об этом в руководстве по Python, здесь .

Здесь также есть хорошая статья о файловой организации проектов Python здесь .

12 голосов
/ 19 января 2009

пользователь импорта

u = user.User () # ошибка в этой строке

Из-за отсутствия __init__, упомянутого выше, вы можете ожидать ImportError, которая прояснит проблему.

Вы не получите его, потому что «пользователь» также является существующим модулем в стандартной библиотеке. Ваш оператор импорта захватывает его и пытается найти класс User внутри него; этого не существует, и только тогда вы получите ошибку.

Как правило, рекомендуется сделать ваш импорт абсолютным:

import Server.Models.user

чтобы избежать такой двусмысленности. Действительно, из Python 2.7 «пользователь импорта» вообще не будет выглядеть относительно текущего модуля.

Если вы действительно хотите относительный импорт, вы можете явно указать его в Python 2.5 или более поздней версии, используя несколько уродливый синтаксис:

from .user import User
9 голосов
/ 10 марта 2012

Правильный способ импортировать модуль, расположенный в родительской папке, если у вас нет стандартной структуры пакета, это:

import os, sys
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.dirname(CURRENT_DIR))

(вы можете объединить последние две строки, но этот способ легче понять).

Это решение является кроссплатформенным и достаточно общим, чтобы его не нужно было изменять в других обстоятельствах.

7 голосов
/ 19 января 2009

Тебе не хватает __init__.py. Из учебника по Python:

Файлы __init__.py необходимы для заставить Python обращаться с каталогами как содержащие пакеты; это сделано для предотвратить каталоги с общим имя, например строка, из непреднамеренно скрывая действительные модули которые происходят позже при поиске модуля дорожка. В простейшем случае __init__.py может быть просто пустым файлом, но он также может выполнять инициализацию код для пакета или установить переменная __all__, описанная позже.

Поместите пустой файл с именем __init__.py в каталог моделей, и все должно быть золотым.

1 голос
/ 20 марта 2014

как вы записываете параметры os.path.dirname .... команда?

import os, sys
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.dirname(CURRENT_DIR))
0 голосов
/ 09 апреля 2019

Проанализировав ответы этих авторов выше - 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 .

0 голосов
/ 25 августа 2016

Мой предпочтительный способ - использовать __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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...