无法在我的测试文件中导入我自己的模块

Can't import my own module in my test file

提问人:Atro_TLT 提问时间:10/30/2023 最后编辑:Atro_TLT 更新时间:10/30/2023 访问量:72

问:

我有以下项目结构:

.
├── README.md
├── document_processing
│   ├── Config.py
│   ├── DocumentParser.py
│   ├── FileChecker.py
│   └── __init__.py
├── indexing.py
└── tests
    ├── CheckFileTest.py
    └── __init__.py

在 CheckFileTest.py 中,我为 FileChecker.py 函数实现了一些测试。

import unittest
from document_processing.Config import Config
from document_processing.FileChecker import FileChecker

class CheckFileTest(unittest.TestCase):
    def __init__(self):
        self.config = Config()
        self.fc = FileChecker(self.config)
    
    def test_not_empty_line(self):
        ...
        
    def test_line_format(self):
        ...
        
if __name__ == "__main__":
    unittest.main()

不幸的是,当我尝试运行测试文件(从项目根目录启动)时,我遇到了这个错误:

Traceback (most recent call last):
  File "/Users/thomaslaurent/Dev/MIRCV_project/tests/CheckFileTest.py", line 3, in <module>
    from document_processing.Config import Config
ModuleNotFoundError: No module named 'document_processing

我已经看到了很多东西,但我无法弄清楚这个结构挡住了什么。

具有相对导入:

from ..document_processing.Config import Config

我收到这个错误:

ImportError: attempted relative import with no known parent package

编辑

根据@sinoroc的评论,我没有将测试作为包,而是创建了一个 setup.py 文件:

from setuptools import setup

setup(
    name="MIRCV_project",
    version="1.0",
    description="",
    author="Thomas LAURENT",
    author_email="",
    packages=["document_processing"],
    install_requires=[],  # external packages acting as dependencies
)

我终于跑了:

python -m pip install --editable .

您可以投票给之前 setup.py 配置@sinoroc答案:如何为独立应用程序制作 setup.py

python python-import python-module python-packaging

评论

1赞 sinoroc 10/30/2023
您的项目是否正确安装(当然,安装为可编辑也可以)?-- 如何“运行测试文件”?
0赞 Atro_TLT 10/30/2023
我使用python3 tests/CheckFileTest.py或vsCode中的运行命令运行测试文件
0赞 sinoroc 10/30/2023
是否确定项目已正确安装,并且其包是可导入的?当你运行类似的东西时会发生什么?python3 -c 'import document_processing; print(document_processing)'
0赞 Atro_TLT 10/30/2023
它实际上工作并打印了:来自“/Users/thomaslaurent/Dev/MIRCV_project/document_processing/__init__.py”的<模块“document_processing>
0赞 sinoroc 10/30/2023
那么这应该有效,我看不出有什么理由不行。 -- 我建议你使用测试套件运行器,比如 pytest(即使我不推荐它,你也可以使用 unittest 作为测试套件运行器:) -- 我不认为你应该求助于使用相对导入,对环境变量进行任何修改,因为你会在互联网上看到建议。充其量,这些是暂时的黑客攻击,但它们不是一个可靠的长期解决方案。python3 -m unittestsys.pathPYTHONPATH

答:

-3赞 Exfell 10/30/2023 #1
from ..document_processing.Config import Config
from ..document_processing.FileChecker import FileChecker

评论

0赞 Atro_TLT 10/30/2023
使用您的解决方案,我遇到以下错误:ImportError:尝试相对导入,没有已知的父包
1赞 Jeremy Caney 10/30/2023
感谢您对 Stack Overflow 社区的贡献。这可能是一个正确的答案,但提供代码的额外解释,以便开发人员能够理解你的推理,这将是非常有用的。这对于不熟悉语法或难以理解概念的新开发人员特别有用。为了社区的利益,您能否编辑您的答案以包含其他详细信息?
-2赞 Alcamtar 10/30/2023 #2

Python 搜索相对于它加载的程序文件的目录。

如果正在运行,则有效根目录(用于包搜索)是 。那不是当前目录,只是包搜索根目录。tests/CheckFileTest.pytests/

对于要从 开始导入,它必须导入 ../document_processing/Config.py。它需要从测试中搜索目录树,而 Python 不这样做。如果它这样做了,它可能会一直回溯到根目录,并最终搜索整个文件系统,这可能会非常慢。Python 仅从给定的搜索根目录向下查找目录树。CheckFileTest.pyConfig.pytests

有几种方法可以解决这个问题。诡计多端的方法是修改搜索路径以包含其他搜索根目录。

例如,如果您希望它相对于您发出命令的当前目录进行搜索(如示例中所示):

import os, sys
sys.path.append(os.getcwd())
from document_processing.Config import Config
from document_processing.FileChecker import FileChecker

或者,如果您可以从任何地方执行该命令,并且确实希望它相对于安装进行导入,则可以执行以下操作:

import sys
sys.path.append('..')
from document_processing.Config import Config
from document_processing.FileChecker import FileChecker

但这只有在同行的情况下才会起作用。document_processingtests

更好的方法是将项目重新组织为单个包,如下所示:

.
├── README.md
├── indexing.py
└── tests
    ├── CheckFileTest.py
    ├── __init__.py
    └── document_processing
        ├── Config.py
        ├── DocumentParser.py
        ├── FileChecker.py
        └── __init__.py

然后,无论您从哪个目录运行程序,从 CheckFileTest.py 导入都将按照您编写的方式工作。

评论

1赞 sinoroc 10/30/2023
如果项目安装正确,则该项目已位于 列出的目录之一中。如果包装和安装正确,几乎从来没有充分的理由进行修改。document_processingsys.pathsys.path
0赞 Brian61354270 10/30/2023
-1 由于 Sinoroc 提到的原因。在运行时搞砸是一个脆弱的创可贴,因为它本来就不应该存在。sys.path
0赞 Brian61354270 10/30/2023
制作子包的建议似乎真的很奇怪。您能澄清一下为什么您认为这是有益的吗?document_processingtests
0赞 Alcamtar 10/31/2023
OP问怎么做。Sys.path 可能是一种 hack 方法(我清楚地标记了它),但它是一种受支持的方法,值得一提。
0赞 Alcamtar 10/31/2023
@Brian61354270 我在这里的目的不是要教如何最好地组织这个特定的项目(据我所知,这可能是一个稻草人),而是解释如何在不使用相对导入的情况下导入。我考虑过更改代码以使测试成为子目录,但这会产生一个更长、更复杂的答案。我选择演示该方法,并留给OP如何最好地组织该项目。