2016-06-28 71 views
1

我已经花了一个小时在Google和SO上过这一个。对不起,再添加一个,但没有一个答案对我来说很合适。从兄弟目录导入Python类

/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 

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

project.py

class PROJECT: 
def __init__(self): 
    stuff 

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

db.py

class DB: 
def __init__(self): 
    stuff 

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

当我尝试运行

python getSomething.py

我得到的错误

Traceback (most recent call last):

File "scripts/getSomething.py", line 4, in < module >

from ..classes import project

ValueError: Attempted relative import in non-package

我在这里错过了什么?

回答

4

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

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

这时你不会有导入错误。


也许有必要快速讨论一下python模块和包。通常,包含Python源代码并具有.py扩展名的文件是一个模块。通常,该模块的名称是文件的名称(无扩展名),但如果直接运行该模块,则该模块的名称为'__main__'。到目前为止,这都是众所周知的,并有文件记录。要导入模块,您只需执行import moduleimport package.module等等。这最后一条进口声明指的是我们现在要讨论的其他东西(“包”)...

包是您可以导入的目录。许多目录不能被导入(例如,他们可能没有python源文件 - 模块 - )。因此,为了解决这种歧义,还要求该目录具有__init__.py文件。当你在你的文件系统中导入一个目录时,python实际上会导入__init__.py模块,并根据__init__.py(如果有的话)中的东西创建相关的包。

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

你可能会问自己:“他们为什么这样设计它?”事实上,我偶尔也问过自己同样的问题。我认为这是因为语言设计师希望为包装提供某些保证。包装应该是为了特定目的而一起工作的单元。它不应该是一个脚本的孤岛,凭借几个随意的文件可以绕过文件系统找到他们需要的其他模块。如果某些东西被设计成作为主要模块运行,那么它可能不应该是程序包的一部分。相反,它应该是一个单独的模块,可以导入包并依赖它。

+0

好吧,那么几件事情: 我的印象是,为每个目录添加'__init __。py'本质上将这些目录定义为一个包?我可能对这里的软件包有一个根本性的误解。为什么主模块永远不在包装中?其次:我的目标是在cron上运行脚本。有没有办法直接将这些类导入到脚本中?创建另一个文件'main.py'多一层看起来似乎不必要的复杂。 – ShaneOH

+1

@ShaneOH - 我试过(尽我所能)编辑我的答案,希望能够澄清任何含糊之处......我希望它有帮助。 – mgilson

+0

谢谢,原始答案和编辑都非常有帮助。所以我有一个最后的问题:如果我想保持这个目录结构并直接运行脚本作为主模块呢?所以没关系,他们不需要成为软件包的一部分。如何将/ classes模块导入同级文件夹中的主模块?然后,我可以从/ scripts和/ project中删除__init __。py吗? – ShaneOH