Python функция импорта не работает в Django с использованием Spyder - PullRequest
0 голосов
/ 18 февраля 2020

Мой Django проект имеет следующую структуру папок, где controllers - это место, где я храню все пользовательские .py файлы:

C:.
│   db.sqlite3
│   manage.py
│
├───myApp
│   │   admin.py
│   │   apps.py
│   │   forms.py
│   │   models.py
│   │   tests.py
│   │   urls.py
│   │   views.py
│   │   widgets.py
│   │   __init__.py
│   │
│   ├───controllers
│   │   │   helpers.py
│   │   │   function.py
│   │   │   __init__.py
│   │   │

Внутри controllers/function.py Я хочу импортировать файл helpers.py ,

Сценарий 1: Если я ввожу from .helpers import foo и запускаю это в Django, тогда я могу импортировать helpers.py, но если я запускаю этот же импорт в Spyder, тогда я get: ImportError: attempted relative import with no known parent package

Сценарий 2: Если я наберу from helpers import foo (без «точки») и запусту это в Django, тогда я получу: ModuleNotFoundError: No module named 'helpers', но это работает в Spyder!

Что мне здесь не хватает с путями (или относительными путями). Мне нужно иметь возможность иметь один python скрипт, который работает в Django и Spyder без необходимости везде удалять ..

Ответы [ 2 ]

0 голосов
/ 18 февраля 2020

В: «Если я запустил этот же импорт в Spyder» => Вы имеете в виду встроенную оболочку python spyder? A: «правильно»

Тогда этого следовало ожидать.

В модуле functions.py вы можете использовать относительный импорт (и это действительно то, что вам нужно), поскольку он будет разрешен относительно текущего модуля ("functions.py").

Когда вы находитесь в интерактивной оболочке, вы НЕ находитесь в модуле, который является частью пакета, поэтому относительный импорт не может работать здесь, и вы должны использовать абсолютный импорт (или импорт относительно вашей текущей работы). директории, которая должна быть первой в вашем sys.path - если, конечно, что-то (IDE или что-то еще) с ней не испортилось. явный относительный импорт (который всегда должен работать и разрешаться для правильного «вспомогательного» модуля или подпакета)

в вашей оболочке, используйте полный путь, соответствующий вашему текущему sys.path

EDIT

Я не полностью понимаю, что вы подразумеваете под "явным относительным импортом" и "квалифицированным путем"

"явным относительным импортом": from .helpers import foo - это относительный импорт (относительно модуля functions), и он явный (синтаксис, используемый явно, означает «искать модуль или подпакет« помощники »в том же пакете, что и я, и на том же уровне»)

* 103 0 * «квалифицированный путь»: ну да, не самая лучшая формулировка, я думаю. Я имел в виду «более или менее абсолютный» импорт с использованием полного python квалифицированного пути от вершины вашего пакета до вашего модуля. Дело в том, что то, что составляет «вершину вашего пакета», зависит от того, что находится в вашем sys.path, что, в свою очередь, может (или нет, в зависимости от нескольких факторов) зависеть от вашего текущего рабочего каталога.

По умолчанию python вставляет текущий каталог в первую позицию вашего sys.path. Затем он использует sys.path для поиска модулей или пакетов (предупреждение: путь, указанный в sys.path, НЕ должен быть полным путем к вашим пакетам, а должен указывать путь к каталогам , содержащим ваших пакетов).

IOW, если вы откроете терминал, перейдите в каталог root вашего django проекта и запустите (стандартную) оболочку python, root вашего проекта будет первым в sys.path и полное имя вашего helpers модуля будет myapps.controllers.helpers. Но если бы вы были в myapps вместо этого, тогда полный путь был бы controllers.helpers ...

Единственный разумный способ на самом деле - убедиться, что у вас никогда не будет пути к пакетам вашего проекта непосредственно в sys.path (Я всегда запускаю ваш код из root проекта). Это не только решает эти надоедливые проблемы с импортом, но и позволяет избежать печально известной «двойной ловушки импорта»

«В модуле functions.py вы можете использовать относительный импорт». Вы имеете в виду, что я могу использовать.?

Да. На самом деле вы даже должны использовать его, если у вас нет веских причин не делать этого, так как это предотвратит потенциальное дублирование модуля helpers другим модулем с тем же именем, которое было бы раньше в вашем sys.path - и в нем четко указывается, из какого helpers модуля или пакета вы импортируете.

Это то, что я делаю в сценарии 1, и оно не работает в Spyder.

Как я уже упоминал в комментарии, «не работает в Spyder» недостаточно, чтобы сказать точно , что не так, потому что мы точно не знаем, что вы выполнение этого «не работает в Spyder» - ни сообщение об ошибке точный И полный FWIW обратной трассировки, оба из которых обычно требуются для вопросов «не работает» (если, конечно, проблема очевидна).

Но если он (как я понял) «запускает оболочку python в Spyder и вводит from . helpers import xxx», то он действительно не будет «работать» - вы можете использовать этот синтаксис только в коде модуля И модуль должен быть частью пакета, а каталог, содержащий этот пакет, должен находиться в вашей sys.path.

. Именно поэтому в оболочке python вы должны использовать абсолютный импорт (" из ххх импорта ггг)). Но затем, какой точный путь зависит от того, что находится в вашем sys.path - что частично зависит от вашего текущего рабочего каталога (по крайней мере, для простой оболочки Python - я не использую Spyder, поэтому не могу сказать, что он делает твоя спина).

Теперь, если Spyder не полностью восприимчив к мозгу, он должен использовать root вашего проекта django в качестве первого элемента в sys.path (или, по крайней мере, иметь этот каталог в sys.path), поэтому полный квалифицированный путь (from myapp.controllers.helpers import foo) должно работать. Если это не так, проверьте свой cwd (os.getcwd()) и sys.path и отредактируйте свой вопрос с помощью:

  • полного описания того, что вы делали точно
  • точное сообщение об ошибке и полный возврат
  • ваш cwd и sys.path

Кроме того, вы, вероятно, хотите прочитать некоторую документацию по импорту Python система, которая, честно говоря, иногда может быть PITA королевского размера.

0 голосов
/ 18 февраля 2020

Предложение Try Except должно сделать это:

try:
    from .helpers import foo
except ImportError:
    from helpers import foo
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...