PYPI包装中的SRC/文件夹是否具有特殊的含义,还是仅是约定?
我正在学习如何根据教程为PYTI打包Python项目()。对于示例项目,他们使用文件夹结构:
packaging_tutorial/
├── LICENSE
├── pyproject.toml
├── README.md
├── src/
│ └── example_package_YOUR_USERNAME_HERE/
│ ├── __init__.py
│ └── example.py
└── tests/
我只是想知道为什么需要 src/
文件夹?它有特殊目的吗?一个人可以直接在顶级文件夹中包含包装吗?例如,会有
packaging_tutorial/
├── LICENSE
├── pyproject.toml
├── README.md
├── example_package_YOUR_USERNAME_HERE/
│ ├── __init__.py
│ └── example.py
└── tests/
任何缺点或引起并发症吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
有一个有趣的博客文章关于此主题;基本上,使用
src
可以防止在项目目录中运行测试时,软件包源文件夹将导入而不是已安装的软件包(并且测试应始终针对安装的软件包进行,以便情况相同至于用户)。考虑以下示例项目,其中正在开发的软件包的名称为
mypkg
。它包含__ INIT __。py
文件和另一个data.txt
non-code资源:此处,
mypkg/__ init __ init __. py
访问> data.txt
资源并加载其内容:脚本
test/test_data.py
检查mypkg.data
实际上包含'foo':
现在,运行
coverage> coverage> coverage> mm pytest
从基本目录中提供这个项目的印象是一切都很好:但是,有一个微妙的问题。运行
coverage Run -M Pytest
Invokespytest
通过python -m pytest
,即使用 -m 开关。如文档中所述,这具有“副作用”:这意味着,在
Mypkg
中导入test/test_data.py
时,它没有导入已安装的版本,但它从源树中导入了软件包mypkg
而不是。现在,让我们进一步假设我们忘了在我们的项目规范中包含
data.txt
资源(毕竟,没有subtest.in
)。因此,该文件实际上不包含在安装mypkg
的版本中(例如,通过python -m pip install.
安装。)。通过直接运行pytest
来揭示这一点:因此,尽管安装了
mypkg
被损坏,但使用coverage
测试通过。该测试没有捕获它,因为它是针对源树而不是安装版本的。如果我们已经使用src
目录来包含mypkg
软件包,则通过-m
添加当前的工作目录不会引起任何问题,例如当前工作目录中没有包装 mypkg 。但是最后,使用
src
不是必需品,而是更多的惯例/最佳实践。例如,请求不使用src
,它们仍然设法成为一种流行和成功的项目。There is an interesting blog post about this topic; basically, using
src
prevents that when running tests from within the project directory, the package source folder gets imported instead of the installed package (and tests should always run against installed packages, so that the situation is the same as for a user).Consider the following example project where the name of the package under development is
mypkg
. It contains an__init__.py
file and anotherDATA.txt
non-code resource:Here,
mypkg/__init__.py
accesses theDATA.txt
resource and loads its content:The script
test/test_data.py
checks thatmypkg.data
actually contains'foo'
:Now, running
coverage run -m pytest
from within the base directory gives the impression that everything is alright with the project:However, there's a subtle issue. Running
coverage run -m pytest
invokespytest
viapython -m pytest
, i.e. using the-m
switch. This has a "side effect", as mentioned in the docs:This means that when importing
mypkg
intest/test_data.py
, it didn't import the installed version but it imported the package from the source tree inmypkg
instead.Now, let's further assume that we forgot to include the
DATA.txt
resource in our project specification (after all, there is noMANIFEST.in
). So this file is actually not included in the installed version ofmypkg
(installation e.g. viapython -m pip install .
). This is revealed by runningpytest
directly:Hence, when using
coverage
the test passed despite the installation ofmypkg
being broken. The test didn't capture this as it was run against the source tree rather than the installed version. If we had used asrc
directory to contain themypkg
package, then adding the current working directory via-m
would have caused no problems, as there is no packagemypkg
in the current working directory anymore.But in the end, using
src
is not a requirement but more of a convention/best practice. For example requests doesn't usesrc
and they still manage to be a popular and successful project.