从兄弟目录导入Python类

Sha*_*eOH 2 python import module package relative-import

我花了过去一小时的时间来浏览Google和SO.很抱歉添加另一个,但没有一个答案对我有用.

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

__init__.py

scripts/
      getSomething.py
      __init__.py

classes/
      project.py
      db.py
      __init__.py
Run Code Online (Sandbox Code Playgroud)

====================

getSomething.py

from ..classes import project
from ..classes import db
Run Code Online (Sandbox Code Playgroud)

====================

project.py

class PROJECT:
def __init__(self):
    stuff
Run Code Online (Sandbox Code Playgroud)

====================

db.py

class DB:
def __init__(self):
    stuff
Run Code Online (Sandbox Code Playgroud)

====================

当我试图跑

python getSomething.py

我收到了错误

Traceback(最近一次调用最后一次):

在<module>中的文件"scripts/getSomething.py",第4行

来自..classes导入项目

ValueError:在非包中尝试相对导入

我在这里错过了什么?

mgi*_*son 5

如错误中所述,您将getSomething作为主模块运行.但是当你不在包中时,你不能打包相对导入.主模块永远不在包中.所以,如果您要getSomething作为包的一部分导入...:

# /VM/repo/main.py
from project.scripts import getSomething
Run Code Online (Sandbox Code Playgroud)

那你就不会有导入错误.


或许对python模块和包进行快速讨论会很有帮助.通常,包含python源代码并具有.py扩展名的文件是一个模块.通常,该模块的名称是文件的名称(无扩展名),但如果直接运行,则该模块的名称为'__main__'.到目前为止,这一切都是众所周知和记录在案的.要导入你只是做一个模块import moduleimport package.module等等.最后一个import语句引用了我们现在要讨论的其他东西("包")......

包是您可以导入的目录.许多目录无法导入(例如,他们可能没有python源文件 - 模块 - 在其中).因此,为了解决这种歧义,还要求目录具有__init__.py文件.当您在文件系统上导入目录时,python实际上会导入__init__.py模块并从中的内容创建关联的包__init__.py(如果有的话).

将所有这些放在一起说明了为什么在一个目录中执行一个文件__init__.py是不够的,python认为该模块是一个包的一部分.首先,模块的名称__main__不是package.filename_sans_extension.其次,一个包的创建不仅依赖于文件系统的结构,但是否该目录(因此__init__.py实际上进口).

你可能会问自己"为什么他们这样设计呢?" 实际上,我偶尔会问自己同样的问题.我认为原因是语言设计者希望对包装有一定的保证.包装应该是为特定目的而共同工作的单元.它不应该是一个脚本的孤岛,凭借一些偶然的__init__.py文件获得了遍历文件系统以找到他们需要的其他模块的能力.如果某些东西被设计为作为主模块运行,那么它可能不应该是包的一部分.相反,它应该是一个单独的模块,导入包并依赖它.