"pytest模块导入ImportError: 没有名为的模块"

4

这个问题之前已经被问了数十次,但我找到的每一个解决方案都对我无效。

我正在使用Python 2.7和pytest来运行测试。

项目/ git仓库的结构如下:

myapp/
    myapp/
        __init__.py           # def main():
                              #    ... stuff
                              # if __name__ == "__main__":
                              #    main()

        __main__.py           # import __init__ as myapp
                              # myapp.main()

        config.yaml           # (app config file)

        myapplib/
                __init__.py   # (Empty file)

                config.py     # Loads {projectroot}/config.yaml
                              # def cfg(): 
                              #    ... stuff
    tests/
        test_stuff.py         # from myapplib.config import cfg

然后我尝试运行tests/test_stuff.py文件,方法如下:

cd {projectroot}
pytest

同时它抱怨道:

myapp/tests/test_stuff.py:38: in <module>
    from myapplib.config import cfg
E   ImportError: No module named myapp.config

我尝试过以下几种方法:

  1. 使用-m导入myapplibmyapp.myapplib
  2. 从不同的目录启动pytest(例如在tests/中)
  3. 使用其他答案中提供的所有路径技巧
  4. 将代码更改为from . import XXX..或任何相对导入选项(但这些都会出现ValueError:尝试在非包中进行相对导入错误)。

值得注意的是,该应用程序本身在项目目录中可以正常执行:

cd {projectroot}
python myapp

......所有配置和路径都没有问题。只是测试无法找到路径。


以下是我目前的完整复制:

https://pyfiddle.io/fiddle/4fa60f5a-02df-43bb-8aa3-03e59ff72650/?m=Saved%20fiddle


2
似乎 myapp.config 不存在。难道不应该是 myapp.myapplib.config 吗?错误似乎与您的代码不匹配。 - Jean-François Fabre
是的,我也尝试过了,但是它会抱怨“ImportError: No module named myapp.myapplib.config”。 - brandonscript
是的,我也试过了。 - brandonscript
我的意思是你说你的代码是 from myapplib.config import cfg,但错误显示为 from myapp.config import cfg。首先澄清这一点。 - Jean-François Fabre
哈,糟糕的红鲱鱼。更新了问题。 - brandonscript
1个回答

2

您正在运行

myapp/tests/test_stuff.py

您需要编辑 test_stuff.py 中的路径,将其指向包含 __init__.pymyapp 文件夹。

我在我的系统上进行了测试(文件名为 test_stuff.py):

import sys,os
sys.path.append(os.path.join(os.path.dirname(__file__),os.pardir,"myapp"))
import myapplib

获取Python模块的完整路径,然后使用其父级目录将Python路径添加到 myapp 的第二层级。

适用于与您配置相同的目录树:

S:\python\myapp\myapp
S:\python\myapp\tests
S:\python\myapp\myapp\myapplib
S:\python\myapp\myapp\myapplib\__init__.py
S:\python\myapp\tests\test_stuff.py

建议:在使用 sys.path.append() 时:

  • 始终使用绝对路径,使用 __file__ 来确保当前目录不会造成干扰。永远不要依赖于当前目录,否则这个技巧只能在特定目录中起作用。
  • 调试:打印你要添加的路径以检查它是否正确。由于它是绝对路径,所以你很容易看到它是否正确。

这里有一个fiddle,包含了你所做的更改的完整测试项目复制:https://pyfiddle.io/fiddle/4fa60f5a-02df-43bb-8aa3-03e59ff72650/?m=Saved%20fiddle - brandonscript
哦,我明白了,你的回答让我觉得我应该把它放在__init__.py中。这没有多大意义,是吧 ;)。是的,那个fiddle只是我试图将所有内容放在一个地方而不是分开的文件中。 - brandonscript
修改 sys.path 只对导入该模块的代码有效。我已经编辑了我的帖子以消除混淆。 - Jean-François Fabre
我不认为这是必要的。你的问题错误在于myapp/tests/test_stuff.py:38: in <module> from myapplib.config import cfg。很高兴它能够工作,因为我花了一些时间重现你的文件树 :) - Jean-François Fabre
我编辑了让我困惑的部分。如果可以的话,请告诉我! - brandonscript
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接