简体   繁体   English

使用pytest时找不到模块

[英]Module Not Found when using pytest

I have a virtualenv that uses Python 3 and am currently using pytest for testing. 我有一个使用Python 3的virtualenv,目前正在使用pytest进行测试。 I've packaged a program called "process_expiring_passwords" and import this package from my general script file called "pep.py". 我已经打包了一个名为“ process_expiring_passwords”的程序,并从名为“ pep.py”的常规脚本文件中导入了此程序包。 I've also used pip in my virtualenv to install my process_expiring_passwords package. 我还在virtualenv中使用了pip来安装process_expiring_passwords软件包。

When I go to run my tests, however, I get the following error: 但是,当我运行测试时,出现以下错误:

ImportError while importing test module '/home/username/projects/process-expiring-passwords/tests/test_process_expiring_passwords.py'. 导入测试模块'/home/username/projects/process-expiring-passwords/tests/test_process_expiring_passwords.py'时,ImportError。

Hint: make sure your test modules/packages have valid Python names. 提示:确保您的测试模块/软件包具有有效的Python名称。

Traceback: tests/test_process_expiring_passwords.py:3: in from process_expiring_passwords import ProcessExpiringPasswords process_expiring_passwords/process_expiring_passwords.py:16: in from process_expiring_passwords.models.ProcessExpiringPasswordsLog 追溯:tests / test_process_expiring_passwords.py:3:来自process_expiring_passwords导入ProcessExpiringPasswords process_expiring_passwords / process_expiring_passwords.py:16:来自process_expiring_passwords.models.ProcessExpiringPasswordsLog

\\ E ModuleNotFoundError: No module named 'process_expiring_passwords.models'; \\ E ModuleNotFoundError:没有名为'process_expiring_passwords.models'的模块; 'process_expiring_passwords' is not a package 'process_expiring_passwords'不是一个软件包

Is there a particular reason why I can use my package from my pep.py general script file while pytest is unable to find said package? 有什么特殊的原因可以使我从pep.py常规脚本文件中使用我的软件包,而pytest找不到该软件包?

The essential parts of the code related to this issue are as follows: 与该问题相关的代码的基本部分如下:

pep.py: pep.py:

from process_expiring_passwords.process_expiring_passwords \
    import ProcessExpiringPasswords

pep = ProcessExpiringPasswords()
pep.process()

process_expiring_passwords/process_expiring_passwords.py: process_expiring_passwords / process_expiring_passwords.py:

from process_expiring_passwords.models.ProcessExpiringPasswordsLog \
    import ProcessExpiringPasswordsLog

class ProcessExpiringPasswords:
    def __init__(self):
        self.example = 0
    def process():
        pepl = ProcessExpiringPasswordsLog()

process_expiring_passwords/models/ProcessExpiringPasswordsLog.py: process_expiring_passwords /模型/ ProcessExpiringPasswordsLog.py:

class ProcessExpiringPasswordsLog():
    def __init__(self):
        self.example = 0

process_expiring_passwords/setup.py: process_expiring_passwords / setup.py:

# ref: https://github.com/pypa/sampleproject/blob/master/setup.py
# ref: http://python-packaging.readthedocs.io/en/latest/minimal.html
from setuptools import setup

setup(
    name='process_expiring_passwords',
    version='0.0.1',
    packages=find_packages(),
    description='Process expiring passwords',
    license='MIT',
    install_requires=[
        'apiclient',
        'google-api-python-client',
        'httplib2',
        'mysqlclient',
        'oauth2client',
        'requests',
        'SQLAlchemy',
    ],
)

tests/test_process_expiring_passwords.py: 测试/ test_process_expiring_passwords.py:

from process_expiring_passwords import ProcessExpiringPasswords

def test_pep():
    pep = ProcessExpiringPasswords()
    assert pep is not None

Project structure: 项目结构:

process_expiring_passwords
    pep.py
    process_expiring_passwords
        __init__.py
        models
            __init__.py
            ProcessExpiringPasswordsLog.py
        process_expiring_passwords.py
        setup.py
    tests
        test_process_expiring_passwords.py

Notes: 笔记:

  • Updated code example and setup.py based on feedback from Matt Messersmith. 根据Matt Messersmith的反馈更新了代码示例和setup.py。

Your code doesn't quite work as posted, I modified it to have the self keyword in your constructors and member functions. 您的代码在发布时无法正常工作,我对其进行了修改,使其在构造函​​数和成员函数中具有self关键字。 After that, I could get pep.py to run. 之后,我可以运行pep.py。

Is there a particular reason why I can use my package from my pep.py general script file while pytest is unable to find said package? 有什么特殊的原因可以使我从pep.py常规脚本文件中使用我的软件包,而pytest找不到该软件包?

Yes, when you are in your top level process_expiring_passwords directory, you can run pep.py , because you'll be getting a "local" import of the package. 是的,当您在顶级process_expiring_passwords目录中时,可以运行pep.py ,因为您将获得软件包的“本地”导入。

The fact that the test doens't run has little to do with pytest , and more to do with what your import statement looks like and the fact that you're not building a package: 测试无法运行的事实与pytest ,而与您的import语句的外观以及您未构建包的事实有关:

from process_expiring_passwords import ProcessExpiringPasswords

You haven't created a package called process_expiring_passwords . 您尚未创建一个名为process_expiring_passwords的包。 You can verify this by doing python setup.py bdist_wheel (or just do sdist and unzip the tarball), unzipping the wheel, and noting that there are no packages present. 您可以通过执行python setup.py bdist_wheel (或仅执行sdist并解压缩tarball),解压滚轮并注意不存在任何软件包来进行验证。

Typically, you need to install the packages python setup.py install (this plops the distributable in your site-packages), and you also have to name the packages in setup.py ( find_packages() is your friend), and then your test should work (more or less) as expected. 通常,您需要安装软件包python setup.py install (这会破坏您的站点软件包中的可分发内容),并且还必须在setup.py中命名这些软件包( find_packages()是您的朋友),然后进行测试应该(或多或少)按预期工作。

HTH. HTH。

Following an extended conversation about this issue, here are the following steps that especially helped based on comments from @hoefling and after adding packages=find_packages(), to setup.py based on answer from @Matt Messersmith: 在就此问题进行了广泛讨论之后,以下步骤基于@hoefling的注释,并根据@Matt Messersmith的回答将packages=find_packages(),添加到setup.py之后,特别有用:

  1. moved setup.py to root project directory setup.py移至根项目目录
  2. deleted __pycache__ files 删除__pycache__文件
  3. made imports relative in main module file 使导入相对于主模块文件

    process_expiring_passwords/process_expiring_passwords.py: process_expiring_passwords / process_expiring_passwords.py:

    from .models.ProcessExpiringPasswordsLog \\ import ProcessExpiringPasswordsLog

  4. ran python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())" 运行python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"

  5. removed old package line from easy-install.pth (which should be found using the resulting path from the previous step) easy-install.pth删除了旧的软件包行(应该使用上一步中的结果路径找到)
  6. ran pip install -e . 运行pip install -e .
  7. added process_expiring_passwords to test file's import section: process_expiring_passwords添加到测试文件的导入部分:

    from process_expiring_passwords.process_expiring_passwords \\ import ProcessExpiringPasswords

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

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