简体   繁体   English

测试和python包结构

[英]Tests and python package structure

I have some problems in structuring my python project. 我在构建我的python项目时遇到了一些问题。 Currently it is a bunch of files in the same folder. 目前它是同一文件夹中的一堆文件。 I have tried to structure it like 我试着像它一样构造它

proj/
  __init__.py
  foo.py
  ...
  bar/
    __init__.py
    foobar.py
    ...
  tests/
    foo_test.py
    foobar_test.py
    ...

The problem is that I'm not able, from inner directories, to import modules from the outer directories. 问题是我无法从内部目录导入外部目录中的模块。 This is particularly annoying with tests. 这对测试尤其烦人。

I have read PEP 328 about relative imports and PEP 366 about relative imports from the main module. 我已经阅读了关于相对进口的PEP 328和关于主要模块的相对进口的PEP 366 But both these methods require the base package to be in my PYTHONPATH. 但是这两种方法都要求基础包在我的PYTHONPATH中。 Indeed I obtain the following error 确实,我得到以下错误

ValueError: Attempted relative import in non-package. ValueError:在非包中尝试相对导入。

So I added the following boilerplate code on top of the test files 所以我在测试文件的顶部添加了以下样板代码

import os, sys
sys.path.append(os.path.join(os.getcwd(), os.path.pardir))

Still I get the same error. 我仍然得到同样的错误。 What is the correct way to 什么是正确的方法

  • structure a package, complete with tests, and 构建一个包,完成测试,和
  • add the base directory to the path to allow imports? 将基目录添加到允许导入的路径?

EDIT As requested in the comment, I add an example import that fails (in the file foo_test.py ) 编辑根据评论中的要求,我添加了一个失败的示例导入(在文件foo_test.py

import os, sys
sys.path.append(os.path.join(os.getcwd(), os.path.pardir))
from ..foo import Foo

When you use the -m switch to run code, the current directory is added to sys.path . 使用-m开关运行代码时,当前目录将添加到sys.path So the easiest way to run your tests is from the parent directory of proj , using the command: 因此,运行测试的最简单方法是使用以下命令从proj的父目录:

python -m proj.tests.foo_test

To make that work, you will need to include an __init__.py file in your tests directory so that the tests are correctly recognised as part of the package. 要使其工作,您需要在tests目录中包含一个__init__.py文件,以便将测试正确识别为包的一部分。

I like to import modules using the full proj.NAME package prefix whenever possible. 我想尽可能使用完整的proj.NAME包前缀导入模块。 This is the approach the Google Python styleguide recommends. 这是Google Python样式指南推荐的方法。

One option to allow you to keep your package structure, use full package paths, and still move forward with development would be to use a virtualenv and put your project in develop mode. 允许您保留包结构,使用完整包路径并继续开发的一个选项是使用virtualenv并将项目置于开发模式。 Your project's setup.py will need to use setuptools instead of distutils , to get the develop command. 您的项目的setup.py将需要使用setuptools而不是distutils来获取develop命令。

This will let you avoid the sys.path.append stuff above: 这样可以避免上面的sys.path.append

% virtualenv ~/virt
% . ~/virt/bin/activate
(virt)~% cd ~/myproject
(virt)~/myproject% python setup.py develop
(virt)~/myproject% python tests/foo_test.py

Where foo_test.py uses: foo_test.py使用的位置:

from proj.foo import Foo

Now when you run python from within your virtualenv your PYTHONPATH will point to all of the packages in your project. 现在,当您从virtualenv中运行python ,您的PYTHONPATH将指向项目中的所有包。 You can create a shorter shell alias to enter your virtualenv without having to type . ~/virt/bin/activate 您可以创建一个较短的shell别名来输入您的virtualenv,而无需键入. ~/virt/bin/activate . ~/virt/bin/activate every time. . ~/virt/bin/activate每次. ~/virt/bin/activate

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

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