以尽可能少的行数完整导入模块内的本地文件

Tom*_*ker 7 python python-module python-import pytest

假设我正在编写一个自定义 PIP 包,其结构如下:

\n
.\n|    setup.py\n\xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 src\n|   |    __init__.py\n|   |    useful_functions_i.py\n|   |    useful_functions_ii.py\n|   |    useful_strings.py\n|\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 tests\n    |    unit_tests.py\n\n
Run Code Online (Sandbox Code Playgroud)\n

假设useful_strings看起来像这样:

\n
.\n|    setup.py\n\xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 src\n|   |    __init__.py\n|   |    useful_functions_i.py\n|   |    useful_functions_ii.py\n|   |    useful_strings.py\n|\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 tests\n    |    unit_tests.py\n\n
Run Code Online (Sandbox Code Playgroud)\n

并且useful_functions_iuseful_functions_ii包含执行以下操作的函数:

\n
USEFUL_STRING_A = "useful-string-a"\nUSEFUL_STRING_B = "useful-string-b"\n...\n
Run Code Online (Sandbox Code Playgroud)\n

我应该如何导入useful_stringsand ?useful_functions_iuseful_functions_ii(这并不是一个看起来那么简单的问题。

\n

如果我使用:

\n
def a_useful_function(a_string):\n    if a_string == useful_strings.USEFUL_STRING_XYZ:\n        return True\n    return False\n
Run Code Online (Sandbox Code Playgroud)\n

src如果我尝试在本地运行一些代码,那么效果会很好;pip install .如果我运行并尝试将代码库用作 PIP 包,它将引发异常。

\n

下一个替代方案是:

\n
import useful_strings\n
Run Code Online (Sandbox Code Playgroud)\n

如果我尝试使用代码库作为 PIP 包,这很有效。当我运行单元测试时,问题就出现了。我使用PyTest;我的pytest.ini开头是:

\n
[pytest]\npythonpath = src\ntestpaths = tests\n...\n
Run Code Online (Sandbox Code Playgroud)\n

而且,如果我按照上面的定义编写单元测试a_useful_function(),相应的测试脚本将包含以下导入语法:

\n
from . import useful_strings\n
Run Code Online (Sandbox Code Playgroud)\n

在这些条件下运行单元测试时,from . import useful_strings语法会引发异常。

\n

我在这个网站上的另一个答案中发现了一个解决方法。(我忘记是哪一个了。)它看起来像这样:

\n
[pytest]\npythonpath = src\ntestpaths = tests\n...\n
Run Code Online (Sandbox Code Playgroud)\n

这确实有效,并且它是一个遍布我当前正在处理的存储库中的解决方案。但它给人的感觉很老套、重复而且不符合Python风格。有更好的方法吗?(这也让 PyLint 抱怨导入订单,虽然我可以忍受这一点,但它变得令人恼火。)

\n

Sam*_*son 0

我认为它只是“本地”运行您的代码(我认为这是您在从命令行开发/运行时使用的术语)这就是问题所在。我将使用以下语法来导入包:

from . import useful_strings
Run Code Online (Sandbox Code Playgroud)

但您需要确保 Python 在运行代码时知道您位于包中。所以运行类似的东西:

from . import useful_strings
Run Code Online (Sandbox Code Playgroud)

(即代替python src/entrypoint.py)你应该没问题。

我还建议使用“ src-layout ”或“ flat-layout ”,如setuptools 文档中所示。conftest.py在根目录中创建文件也可以帮助 pytest 找到源代码,因此测试也可以import my_package不引用src,请参阅https://docs.pytest.org/en/latest/explanation/pythonpath.html了解更多详细信息或在pytestPYTHONPATH中搜索conftest.py文件有什么用?