【问题标题】:Forced to use inconsistent file import paths in Python (/Django)强制在 Python (/Django) 中使用不一致的文件导入路径
【发布时间】:2010-11-12 11:50:34
【问题描述】:

我最近在 Django (Python) 中导入时遇到了一些问题……最好用文件图来解释:

- project/
    - application/
        - file.py
    - application2/
        - file2.py

project/application/file.py 我有以下内容:

def test_method():
    return "Working"

问题出现在project/application2/file2.py,当我尝试从上面导入方法时:

from application.file import test_method

通常有效,但有时无效。

from project.application.file import test_method

确实有效,但它违反了 Django 的可移植性准则,因为项目文件夹必须始终使用相同的名称。

我不介意,但事实上这个问题的发生不一致,大多数时候省略project 是好的,但偶尔不是(据我所知,没有任何理由)。

我几乎可以保证我在做一些愚蠢的事情,但是有人经历过吗?将project 放在所有相关导入之前以保持一致会更好吗?老实说,project 文件夹名称不太可能改变,我只是希望尽可能遵守指导方针。

【问题讨论】:

  • 请包括 PYTHONPATH 设置,从它工作的时间和不工作的时间开始。

标签: python django import path


【解决方案1】:

要导入以查找模块,它需要位于 sys.path 中。通常,这包括“”,因此它会搜索当前目录。如果您从项目中加载“应用程序”,它会找到它,因为它在当前目录中。

好的,这是显而易见的东西。一个令人困惑的地方是 Python 会记住加载了哪些模块。如果您加载应用程序,那么您加载应用程序2 导入应用程序,模块“应用程序”已经加载。它不需要在磁盘上找到它;它只使用已经加载的那个。另一方面,如果您还没有加载应用程序,它会搜索它——但找不到它,因为它与加载它的目录(“.”)不在同一个目录中,或者在其他任何地方路径。

这可能会导致导入有时有效有时无效的奇怪情况;仅在已加载时才有效。

如果您希望能够将这些模块作为“应用程序”加载,那么您需要安排将 project/ 附加到 sys.path。

(相对导入听起来相关,但似乎 application 和 application2 是单独的包——相对导入用于在同一个包中导入。)

最后,请务必始终将整个事物视为一个包,或者始终将每个应用程序视为自己的包。不要混搭。如果 package/ 在路径中(例如 sys.path 包括 package/..),那么您确实可以执行“from package.application import foo”,但如果您还执行“from application import foo”,则可能Python 没有意识到它们是同一个东西——它们的名字不同,它们在不同的路径中——最终加载了它的两个不同的副本,这是你绝对不想要的。

【讨论】:

    【解决方案2】:

    如果你深入研究 django 的哲学,你会发现,一个项目就是一个应用程序的集合。其中一些应用程序可能依赖于其他应用程序,这很好。但是,您始终想要的是使您的应用程序可插入,以便您可以将它们移动到不同的项目并在那里使用它们。为此,您需要删除代码中与您的项目相关的所有内容,因此在进行导入时您会这样做。

    from aplication.file import test_method
    

    这将是 django 的方式。格伦回答了你为什么会出错,所以我不会进入那部分。当你运行命令启动一个新项目时:

    django-admin.py startproject myproject
    这将创建一个文件夹,其中包含 django 需要的一堆文件,manage.py 设置,py 等,但它会为你做另一件事。它会将文件夹“myproject”放在你的 python 路径上。简而言之,这意味着您在该文件夹中放置的任何应用程序都可以像上图所示那样导入。你不需要使用 django-admin.py 来启动一个项目,因为没有什么神奇的事情发生,它只是一个捷径。所以你可以把你的应用程序文件夹放在任何地方,你只需要把它们放在 python 路径上,这样你就可以直接从它们导入,并使你的代码项目独立,这样它就可以很容易地用于任何未来的项目,遵守 DRY 原则django 是建立在它之上的。

    【讨论】:

      【解决方案3】:

      最好始终使用相同的方式导入 - 例如,使用 project.app.models - 因为否则,您可能会发现您的模块被导入了两次,这有时会导致 this question 中讨论的模糊错误。

      【讨论】:

      • 唉,Django 自己把__init__.py 文件放在项目目录中把项目目录放在sys.path 上。虽然总是省略项目名称是正确的做法,但对于 Django 来说,这仍然是一个丑陋的 hack(他们应该只是从项目目录中省略了 __init__.py 文件)
      猜你喜欢
      • 2014-06-24
      • 1970-01-01
      • 1970-01-01
      • 2018-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-19
      • 1970-01-01
      相关资源
      最近更新 更多