繁体   English   中英

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

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

我的 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 中运行相同的导入,那么我得到: ImportError: attempted relative import with no known parent package

场景 2:如果我输入from helpers import foo (没有“点”)并在 Django 中运行它,那么我得到: ModuleNotFoundError: No module named 'helpers' but it works in Spyder!

我在这里缺少什么路径(或相对路径)。 我需要能够在 Django 和 Spyder 中运行一个 python 脚本,而不必删除. 到处。

问:“如果我在 Spyder 中运行相同的导入”=> 你的意思是在 spyder 的集成 python shell 中吗? 答:“正确”

那么就值得期待了。

在functions.py 模块中,您可以使用相对导入(这实际上是您想要的),因为它将相对于当前模块(“functions.py”)进行解析。

当您在交互式 shell 中时,您不在包中的模块中,因此相对导入不能在这里工作,您必须使用绝对导入(或相对于当前工作目录的导入,这应该是成为你sys.path第一个——当然除非有东西(IDE 或其他)弄乱了它。

爱荷华州:

  • 在您的模块中,保持显式相对导入(它应该始终有效并解析为正确的“助手”模块或子包)
  • 在您的 shell 中,使用与您当前的sys.path匹配的限定路径

编辑

我不完全理解“显式相对导入”和“限定路径”的意思

“显式相对导入”: from .helpers import foo - 它是相对导入(相对于functions模块),并且是显式的(显式使用的语法意味着“在与我和我相同的包中查找‘helpers’模块或子包在同一级别")

“合格的路径”:嗯,是的,我猜不是最好的公式。 我的意思是使用从包顶部到模块的完整 python 限定路径的“或多或少绝对”导入。 关键是什么构成“您的包的顶部”取决于您的sys.path ,而这又可能(或不,取决于几个因素)取决于您当前的工作目录。

默认情况下,python 在sys.path第一个位置插入当前目录。 然后它使用sys.path来查找模块或包(警告: sys.path列出的路径不应是包的完整路径,而是包含包的目录的路径)。

IOW,如果你打开一个终端,cd 到你的 django 的项目根目录并启动一个(标准)python shell,你的项目的根将在sys.path在第一位,你的helpers模块的限定名称将是myapps.controllers.helpers 但是,如果您在myapps那么完整路径将是controllers.helpers ...

唯一明智的方法实际上是确保您的sys.path永远不会直接包含任何项目的包路径(IOW 始终从项目的根目录运行您的代码)。 这不仅解决了那些讨厌的导入问题,还避免了臭名昭著的“双重导入陷阱”

“在functions.py 模块中,您可以使用相对导入”。 你的意思是我可以使用 .?

是的。 实际上,您甚至应该使用它,除非您有令人信服的理由不使用它,因为它会防止在您的sys.path之前出现的另一个同名模块对helpers模块的潜在影响 - 并且它非常明确地说明了哪个helpers模块或您要从中导入的包。

这就是我在场景 1 中所做的,它在 Spyder 中不起作用。

正如我在评论已经mentionned,“确实在Spyder的不工作”是不够的,说不清楚什么是错的,因为我们不知道自己在做什么是“不以Spyder的工作” -也没有确切的错误信息和完整的回溯 FWIW,这两者通常都是“不起作用”问题所必需的(当然,除非问题很明显)。

但是如果它(正如我所理解的)“在 Spyder 中启动一个 python shell 并from . helpers import xxx ”那么它确实不会“工作” - 你只能在模块代码中使用这种语法,并且模块必须是一部分一个包,并且包含这个包的目录必须在你的sys.path

这就是为什么在 python shell 中,您必须使用绝对导入(“from xxx import yyy”)。 但是,哪个确切路径取决于您的sys.path - 这部分取决于您当前的工作目录(至少对于普通的 Python shell - 我不使用 Spyder,所以我不知道它在您背后做什么)。

现在,如果 Spyder 不是完全脑残,它应该使用 django 项目的根作为sys.path第一个元素(或者至少在sys.path有这个目录),所以完整的限定路径( from myapp.controllers.helpers import foo应该工作。 如果没有,请检查您的 cwd( os.getcwd() )和您的sys.path ,并使用以下内容编辑您的问题:

  • 究竟是做什么的完整描述
  • 确切的错误消息和完整的回溯
  • 你的 cwd 和 sys.path

此外,您可能想阅读一些关于 Python 导入系统的文档——公平地说,有时它可能是一个特大号的 PITA。

一个 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