用__init __。py

时间:2015-08-04 12:47:35

标签: python terminal python-import directory-structure pytest

无论我如何构建代码文件和__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文件在同一目录中,也是空的。

1 个答案:

答案 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