简体   繁体   English

从同级目录导入Python类

[英]Importing Python class from sibling directory

I've spent the past hour going through Google and SO on this one. 过去一个小时,我在Google和SO上花费了一个小时。 Sorry for adding yet another, but none of the answers are quite working for me. 抱歉,我又添加了一个,但所有答案对我来说都不起作用。

My Directory structure in /VM/repo/project is: 我的目录结构在/VM/repo/project是:

__init__.py

scripts/
      getSomething.py
      __init__.py

classes/
      project.py
      db.py
      __init__.py

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

getSomething.py getSomething.py

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

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

project.py project.py

class PROJECT:
def __init__(self):
    stuff

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

db.py db.py

class DB:
def __init__(self):
    stuff

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

When I try to run 当我尝试跑步

python getSomething.py python getSomething.py

I get the error 我得到错误

Traceback (most recent call last): 追溯(最近一次通话):

File "scripts/getSomething.py", line 4, in < module > <模块>中的文件“ scripts / getSomething.py”,第4行

from ..classes import project 从..classes导入项目

ValueError: Attempted relative import in non-package ValueError:尝试非包中的相对导入

What am I missing here? 我在这里想念什么?

As stated in the error, you're running getSomething as a main module. 如错误所述,您正在将getSomething作为主要模块运行。 But you can't do package relative imports when you aren't in a package. 但是,当您不在包中时,就不能打包相对导入。 The main module is never in a package. 主模块从不在包装中。 So, if you were to import getSomething as part of a package...: 因此,如果要将getSomething作为软件包的一部分导入...:

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

Then you would not have the import errors. 这样就不会出现导入错误。


Perhaps it is helpful to have a quick discussion on python modules and packages. 快速讨论python模块和软件包可能会有所帮助。 In general, a file that contains python source code and has the .py extension is a module. 通常,包含python源代码且扩展名为.py的文件是一个模块。 Typically that module's name is the name of the file (sans extension), but if you run it directly, that module's name is '__main__' . 通常,该模块的名称是文件的名称(无扩展名),但是如果直接运行它,则该模块的名称是'__main__' So far, this is all well known and documented. 到目前为止,这都是众所周知的并有文件记载。 To import a module you just do import module or import package.module and so on. 要导入模块,只需import moduleimport package.module等等。 This last import statement refers to something else (a "package") which we'll talk about now... 最后一个import语句引用了我们现在要讨论的其他内容(“包”)。

Packages are directories that you can import. 软件包是可以导入的目录。 Many directories can't be imported (eg maybe they have no python source files -- modules -- in them). 许多目录无法导入(例如,其中可能没有python源文件-模块)。 So to resolve this ambiguity, there is also the requirement that the directory has an __init__.py file. 因此,要解决这种歧义,还需要目录具有__init__.py文件。 When you import a directory on your filesystem, python actually imports the __init__.py module and creates the associated package from the things in __init__.py (if there are any). 当你输入你的文件系统的目录,蟒蛇竟进口__init__.py模块,并创建从所有的事物在相关包__init__.py (如果有的话)。

Putting all of this together shows why executing a file inside a directory that has an __init__.py is not enough for python to consider the module to be part of a package. 将所有这些放在一起可以说明为什么在具有__init__.py的目录中执行文件不足以使python将模块视为包的一部分。 First, the name of the module is __main__ , not package.filename_sans_extension . 首先,模块的名称是__main__ ,而不是package.filename_sans_extension Second, the creation of a package depends not just on the filesystem structure, but on whether the directory (and therefore __init__.py was actually imported). 其次,程序包的创建不仅取决于文件系统结构,还取决于目录(以及是否实际上导入了__init__.py )。

You might be asking yourself "Why did they design it this way?" 您可能会问自己“他们为什么设计这种方式?” Indeed, I've asked myself that same question on occasion. 确实,我有时会问自己同样的问题。 I think that the reason is because the language designers want certain guarantees to be in place for a package. 我认为原因是因为语言设计人员希望为包装提供一定的保证。 A package should be a unit of things which are designed to work together for a specific purpose. 包装应是为特定目的而协同工作的事物单元。 It shouldn't be a silo of scripts that by virtue of a few haphazard __init__.py files gain the ability to walk around the filesystem to find the other modules that they need. 借助于一些偶然的__init__.py文件,它不应成为脚本的孤岛,而__init__.py文件却具有遍历文件系统以查找所需的其他模块的能力。 If something is designed to be run as a main module, then it probably shouldn't be part of the package. 如果某些东西被设计为可以作为主模块运行,那么它可能不应该是该包的一部分。 Rather it should be a separate module that imports the package and relies on it. 而是应该是一个单独的模块,该模块可以导入并依赖该程序包。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM