无论我如何构建代码文件和__init__.py
文件中的导入,我似乎无法正确执行运行测试的程序和使用pytest
。当我的项目结构如下所示时,如何编写导入:
src/
__init__.py
VocableFileWriter.py
WordListHelper.py
WordListReader.py
XLDAttributeValueAdder.py
exceptions/
__init__.py
XMLInvalidException.py
XMLParseException.py
gui/
__init__.py
GTKSignal.py
XLDAttributeValueAdderWindow.py
test/
__init__.py
test_XLDAttributeValueAdder.py
xmlparser/
__init__.py
XMLParser.py
目前,我有这样的人:
在__init__.py
文件中,我有这样的导入(src/__init__.py
):
from src import *
from src.exceptions import *
from src.xmlparser import *
并在子包(src/xmlparser/__init__.py
)中:
from src.xmlparser import *
所以我猜这些是模块的项目绝对路径。 在代码文件本身我导入如下:
import os
import sys
from VocableFileWriter import VocableFileWriter
from XLDAttributeValueAdder import XLDAttributeValueAdder
但是,当我使用:
执行src
上方目录中的代码时
./src/main.py
它告诉我:
Traceback (most recent call last):
File "./src/main.py", line 6, in <module>
from VocableFileWriter import VocableFileWriter
File "/home/xiaolong/Development/PycharmProjects/xld-attribute-value-adder/src/VocableFileWriter.py", line 2, in <module>
from XMLInvalidException import XMLInvalidException
ImportError: No module named 'XMLInvalidException'
它曾经是一个PyCharm项目,但我无法使用PyCharm在不使用PyCharm但从终端运行时使用的导入结构运行,所以我决定我想要整个导入的东西掌握在自己手中。所以不要因为它在PyCharm目录中而感到困惑。
我还希望能够使用例如:
执行测试py.test src/test/test_XLDAttributeValueAdder.py
我该如何解决这个烂摊子?
修改#1: 我让程序运行一次,但后来测试抱怨缺少模块,可能是因为它在另一个子目录中,我尝试了很多配置,我不知道我的程序是如何运行的。如果可能的话,请添加一些解释为什么某个结构是正确的,并且适用于测试和程序本身。
修改#2:
我已经设法让测试现在运行,但现在该程序已经不再运行了。
我清空了所有__init__.py
文件,并在代码文件中仅使用了项目绝对路径,如下所示(src/test/test_XLDAttributeValueAdder.py
):
from src.VocableFileWriter import VocableFileWriter
from src.WordListHelper import WordListHelper
from src.WordListReader import WordListReader
from src.XLDAttributeValueAdder import XLDAttributeValueAdder
from src.exceptions.XMLInvalidException import XMLInvalidException
from src.exceptions.XMLParseException import XMLParserException
from src.xmlparser.XMLParser import XMLParser
from src.test.path_helper import go_up
from src.test.path_helper import go_in
和main.py
:
from src.VocableFileWriter import VocableFileWriter
from src.XLDAttributeValueAdder import XLDAttributeValueAdder
./src/main.py
的输出:
./src/main.py
Traceback (most recent call last):
File "./src/main.py", line 6, in <module>
from src.VocableFileWriter import VocableFileWriter
ImportError: No module named 'src'
修改#3: 我尝试过这样的相对导入方式:
main.py
向上移动了一个目录结构现在看起来像这样:
main.py
src/
__init__.py
VocableFileWriter.py
WordListHelper.py
WordListReader.py
XLDAttributeValueAdder.py
exceptions/
__init__.py
XMLInvalidException.py
XMLParseException.py
gui/
__init__.py
GTKSignal.py
XLDAttributeValueAdderWindow.py
test/
__init__.py
test_XLDAttributeValueAdder.py
xmlparser/
__init__.py
XMLParser.py
__init__.py
个文件为空main.py
文件相对进口看起来像这样:
import os
import sys
from .src.VocableFileWriter import VocableFileWriter
from .src.XLDAttributeValueAdder import XLDAttributeValueAdder
当我尝试运行main.py
文件时:
Traceback (most recent call last):
File "main.py", line 6, in <module>
from .src.VocableFileWriter import VocableFileWriter
SystemError: Parent module '' not loaded, cannot perform relative import
但是,__init__.py
文件与main.py
文件在同一目录中,也是空的。
答案 0 :(得分:1)
您最好使用相对进口。
在 src / __ init __。py 中执行from src import *
时,您只会在调用导入之前导入您已定义的任何内容。最有可能的是什么都没有。如果您已经定义了__all__
变量,那么您将从中获取子模块,但如果尚未定义变量,则可能还需要AttributeError
。
因此,在您需要的地方明确导入您需要的模块,如
from .VocableFileWriter import VocableFileWriter
from .exceptions.XMLInvalidException import XMLInvalidException
或者说在 src / gui / GTKSignal.py
中from ..exceptions.XMLInvalidException import XMLInvalidException
您也可以使用编辑#2 中提到的项目绝对路径。
此外,在调用./src/main.py
时,您的路径出现问题。在这种情况下,包含src
的目录不在路径中。相反,./src/
在路径中。因此,python不再认为它是一个包,因为没有其他具有该名称的包,导入失败。
而是将main.py
模块放在与src
包相同的目录中,或将其称为具有python -m src.main
的模块。这样做,您也可以将其重命名为 src / main .py ,并使用python -m src
调用包instad。
使用第一种方法时,main
应使用绝对导入结构。只需将其视为您放置在计算机上任何位置的模块,而您的src
软件包位于其他位置,可以通过Python找到它,就像系统安装的任何其他模块或软件包一样。当它位于包本身之外时,它没有什么不同,因为当前目录位于sys.path
。
main.py
import os
import sys
from src.VocableFileWriter import VocableFileWriter
from src.XLDAttributeValueAdder import XLDAttributeValueAdder