2

我的目录结构/VM/repo/project是:

__init__.py

scripts/
      getSomething.py
      __init__.py

classes/
      project.py
      db.py
      __init__.py

getSomething.py

from ..classes import project
from ..classes import db

项目.py

class PROJECT:
def __init__(self):
    stuff

数据库.py

class DB:
def __init__(self):
    stuff

当我尝试跑步时

python getSomething.py

我得到错误

Traceback(最近一次调用最后一次):
文件“scripts/getSomething.py”,第 4 行,在 <module>
from ..classes import project
ValueError: Attempted relative import in non-package

我在这里想念什么?

4

1 回答 1

5

如错误中所述,您getSomething作为主模块运行。但是当您不在包中时,您不能进行包相对导入。主模块从不在包中。getSomething因此,如果您要作为包的一部分导入...:

# /VM/repo/main.py
from project.scripts import getSomething

那么你就不会有导入错误。


快速讨论一下 python 模块和包可能会有所帮助。通常,包含 python 源代码并具有.py扩展名的文件是模块。通常,该模块的名称是文件的名称(无扩展名),但如果您直接运行它,该模块的名称是'__main__'. 到目前为止,这一切都是众所周知的并且有据可查。要导入你刚刚做的模块import module等等import package.module。最后一个 import 语句指的是我们现在要讨论的其他东西(“包”)......

包是您可以导入的目录。许多目录无法导入(例如,它们可能没有 python 源文件——模块——在其中)。所以为了解决这个歧义,还需要目录有一个__init__.py文件。当您在文件系统上导入目录时,python 实际上会导入__init__.py模块并从其中的东西__init__.py(如果有的话)创建关联的包。

将所有这些放在一起说明了为什么在具有 的目录中执行文件__init__.py不足以让 python 将模块视为包的一部分。首先,模块的名称是__main__,而不是package.filename_sans_extension。其次,包的创建不仅取决于文件系统结构,还取决于目录是否(因此__init__.py实际上被导入)。

您可能会问自己“他们为什么要这样设计?” 事实上,我有时也会问自己同样的问题。我认为原因是语言设计者希望为包提供某些保证。包应该是为特定目的而设计的事物单元。它不应该是一个脚本孤岛,凭借一些杂乱无章的__init__.py文件获得在文件系统中四处走动以找到他们需要的其他模块的能力。如果某些东西被设计为作为主模块运行,那么它可能不应该是包的一部分。相反,它应该是一个单独的模块来导入包并依赖它。

于 2016-06-28T17:40:08.480 回答