简体   繁体   English

Python 函数导入在使用 Spyder 的 Django 中不起作用

[英]Python function import not working in Django using Spyder

My Django project has the following folder structure where controllers is where I keep all custom .py files:我的 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
│   │   │

Inside controllers/function.py I want to import the file helpers.py .controllers/function.py我想导入文件helpers.py

Scenario 1: If I type from .helpers import foo and run this in Django, then I am able to import helpers.py, but if I run this same import in Spyder then I get: ImportError: attempted relative import with no known parent package场景 1:如果我输入from .helpers import foo并在 Django 中运行它,那么我可以导入 helpers.py,但是如果我在 Spyder 中运行相同的导入,那么我得到: ImportError: attempted relative import with no known parent package

Scenario 2: If I type from helpers import foo (without the "dot") and run this in Django, then I get: ModuleNotFoundError: No module named 'helpers' but it works in Spyder!场景 2:如果我输入from helpers import foo (没有“点”)并在 Django 中运行它,那么我得到: ModuleNotFoundError: No module named 'helpers' but it works in Spyder!

What am I missing here with the paths (or relative paths).我在这里缺少什么路径(或相对路径)。 I need to be able to have one python script that works in Django and Spyder without having to remove the .我需要能够在 Django 和 Spyder 中运行一个 python 脚本,而不必删除. everywhere.到处。

Q : "If I run this same import in Spyder" => do you mean in spyder's integrated python shell ?问:“如果我在 Spyder 中运行相同的导入”=> 你的意思是在 spyder 的集成 python shell 中吗? A : "correct"答:“正确”

Then it's to be expected.那么就值得期待了。

In the functions.py module, you can use a relative import (and that's actually what you want) because it will be resolved relatively to the current module ("functions.py").在functions.py 模块中,您可以使用相对导入(这实际上是您想要的),因为它将相对于当前模块(“functions.py”)进行解析。

When you're in the interactive shell, you are NOT in a module that's part of a package so relative imports cannot work here, and you have to use an absolute import (or an import relative to your current working directory, which is supposed to be first in your sys.path - unless something (IDE or else) messed with it of course.当您在交互式 shell 中时,您不在包中的模块中,因此相对导入不能在这里工作,您必须使用绝对导入(或相对于当前工作目录的导入,这应该是成为你sys.path第一个——当然除非有东西(IDE 或其他)弄乱了它。

IOW:爱荷华州:

  • in your module, keep the explicit relative import (which should always work AND resolve to the correct "helpers" module or sub-package)在您的模块中,保持显式相对导入(它应该始终有效并解析为正确的“助手”模块或子包)
  • in your shell, use a qualified path that matches your current sys.path在您的 shell 中,使用与您当前的sys.path匹配的限定路径

EDIT编辑

I don't fully comprehend what you mean by both "explicit relative import" and "qualified path"我不完全理解“显式相对导入”和“限定路径”的意思

"explicit relative import" : from .helpers import foo - it's a relative import (relative to the functions module), and it's explicit (the syntax used explicitely means "look for a 'helpers' module or subpackage in the same package as me and at the same level") “显式相对导入”: from .helpers import foo - 它是相对导入(相对于functions模块),并且是显式的(显式使用的语法意味着“在与我和我相同的包中查找‘helpers’模块或子包在同一级别")

"qualified path": well yes not the best possible formulation I guess. “合格的路径”:嗯,是的,我猜不是最好的公式。 I meant a "more or less absolute" import using the full python qualified path from your package's top to your module.我的意思是使用从包顶部到模块的完整 python 限定路径的“或多或少绝对”导入。 The point is that what constitutes "your package's top" depends on what's in your sys.path , which in turn might (or not, depending on a few factors) depend on your current working directory.关键是什么构成“您的包的顶部”取决于您的sys.path ,而这又可能(或不,取决于几个因素)取决于您当前的工作目录。

By default, python inserts the current directory in first position of your sys.path .默认情况下,python 在sys.path第一个位置插入当前目录。 Then it uses the sys.path to find modules or packages (warning: the path listed in sys.path should NOT be the full path to your packages, but path to the directories containing your packages).然后它使用sys.path来查找模块或包(警告: sys.path列出的路径不应是包的完整路径,而是包含包的目录的路径)。

IOW, if you open a terminal, cd to your django's project root directory and launch a (standard) python shell, your project's root will come first in sys.path and the qualified name to your helpers module will be myapps.controllers.helpers . IOW,如果你打开一个终端,cd 到你的 django 的项目根目录并启动一个(标准)python shell,你的项目的根将在sys.path在第一位,你的helpers模块的限定名称将是myapps.controllers.helpers But if you were in myapps instead then the full path would be controllers.helpers ...但是,如果您在myapps那么完整路径将是controllers.helpers ...

The only sane way is actually to make sure you never have any of your project's packages path directly in your sys.path (IOW to always run your code from the project's root).唯一明智的方法实际上是确保您的sys.path永远不会直接包含任何项目的包路径(IOW 始终从项目的根目录运行您的代码)。 This not only solves those pesky import issues, but also avoids the infamous "double import trap"这不仅解决了那些讨厌的导入问题,还避免了臭名昭著的“双重导入陷阱”

"In the functions.py module, you can use a relative import". “在functions.py 模块中,您可以使用相对导入”。 You mean I can use the .?你的意思是我可以使用 .?

Yes.是的。 Actually you even should use it unless you have a compelling reason not to, as it will prevent potential shadowing of the helpers module by another module by the same name that would come before in your sys.path - and it makes very explicit which helpers module or package you're importing from.实际上,您甚至应该使用它,除非您有令人信服的理由不使用它,因为它会防止在您的sys.path之前出现的另一个同名模块对helpers模块的潜在影响 - 并且它非常明确地说明了哪个helpers模块或您要从中导入的包。

This is what I am doing in Scenario 1 and it does not work in Spyder.这就是我在场景 1 中所做的,它在 Spyder 中不起作用。

As I already mentionned in a comment, "does not work in Spyder" is not enough to tell exactly what's wrong, because we don't know exactly what you're doing that "does not work in Spyder" - nor the exact error message AND full traceback FWIW, both of which are usually required for "does not work" questions (unless the issue is obvious of course).正如我在评论已经mentionned,“确实在Spyder的不工作”是不够的,说不清楚什么是错的,因为我们不知道自己在做什么是“不以Spyder的工作” -也没有确切的错误信息和完整的回溯 FWIW,这两者通常都是“不起作用”问题所必需的(当然,除非问题很明显)。

But if it's (as I understood it) "launching a python shell in Spyder and typing from . helpers import xxx " then it will indeed not "work" - you can only use this syntax in module code, AND the module has to be part of a package, AND the directory containing this package has to be in your sys.path .但是如果它(正如我所理解的)“在 Spyder 中启动一个 python shell 并from . helpers import xxx ”那么它确实不会“工作” - 你只能在模块代码中使用这种语法,并且模块必须是一部分一个包,并且包含这个包的目录必须在你的sys.path

Which is why, in a python shell, you must use an absolute import ("from xxx import yyy").这就是为什么在 python shell 中,您必须使用绝对导入(“from xxx import yyy”)。 But then, which exact path depends on what's in your sys.path - which partly depends on your current working directory (at least for a plain Python shell - I don't use Spyder so I can't tell what it's doing behind your back).但是,哪个确切路径取决于您的sys.path - 这部分取决于您当前的工作目录(至少对于普通的 Python shell - 我不使用 Spyder,所以我不知道它在您背后做什么)。

Now if Spyder is not totally braindead, it should use your django project's root as first element in sys.path (or at least have this directory in sys.path ), so the full qualified path ( from myapp.controllers.helpers import foo ) should work.现在,如果 Spyder 不是完全脑残,它应该使用 django 项目的根作为sys.path第一个元素(或者至少在sys.path有这个目录),所以完整的限定路径( from myapp.controllers.helpers import foo应该工作。 If it doesn't, check your cwd ( os.getcwd() ) and your sys.path , and edit your question with:如果没有,请检查您的 cwd( os.getcwd() )和您的sys.path ,并使用以下内容编辑您的问题:

  • a complete description of what you were doing exactly究竟是做什么的完整描述
  • the exact error message and full traceback确切的错误消息和完整的回溯
  • your cwd and sys.path你的 cwd 和 sys.path

Also, you probably want to read some documentation on Python's import system - which, to be fair, can be a king size PITA sometimes.此外,您可能想阅读一些关于 Python 导入系统的文档——公平地说,有时它可能是一个特大号的 PITA。

A Try Except clause should do it:一个 Try except 子句应该这样做:

try:
    from .helpers import foo
except ImportError:
    from helpers import foo

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM