开发者提示和技巧#

提高效率和保持理智的技巧#

在本节中,我们收集了一些有用的建议和工具,这些建议和工具可以提高您在审查拉取请求、运行单元测试等方面的质量。其中一些技巧包括需要浏览器扩展(如 TamperMonkeyGreaseMonkey)的用户脚本;要设置用户脚本,您必须安装、启用并运行其中一个扩展。我们以 GitHub gist 的形式提供用户脚本;要安装它们,请在 gist 页面上单击“原始”按钮。

在拉取请求中折叠和展开过时的差异#

当相应的代码行在期间发生更改时,GitHub 会隐藏 PR 上的讨论。这个 用户脚本 提供了一个快捷键(在撰写本文时为 Control-Alt-P,但请查看代码以确保),可以一次展开所有这些隐藏的讨论,以便您可以赶上进度。

将拉取请求检出为远程跟踪分支#

在您的本地分支中,将以下行添加到您的 .git/config 中,位于 [remote "upstream"] 标题下

fetch = +refs/pull/*/head:refs/remotes/upstream/pr/*

然后,您可以使用 git checkout pr/PR_NUMBER 导航到具有给定编号的拉取请求的代码。(在此 gist 中了解更多信息。)

在拉取请求中显示代码覆盖率#

要覆盖 CodeCov 持续集成生成的代码覆盖率报告,请考虑使用 此浏览器扩展。每行的覆盖率将显示为行号后面的彩色背景。

有用的 pytest 别名和标志#

完整的测试套件需要相当长的时间才能运行。为了更快地迭代,可以使用 pytest 选择器选择测试的子集。特别是,可以运行 基于其节点 ID 的单个测试

pytest -v sklearn/linear_model/tests/test_logistic.py::test_sparsify

或使用 -k pytest 参数 根据测试名称选择测试。例如,

pytest sklearn/tests/test_common.py -v -k LogisticRegression

将运行 LogisticRegression 估计器的所有 通用测试

当单元测试失败时,以下技巧可以使调试更容易

  1. 命令行参数 pytest -l 指示 pytest 在发生故障时打印局部变量。

  2. 参数 pytest --pdb 在发生故障时进入 Python 调试器。要改为进入丰富的 IPython 调试器 ipdb,您可以设置一个 shell 别名为

    pytest --pdbcls=IPython.terminal.debugger:TerminalPdb --capture no
    

其他可能变得有用的 pytest 选项包括

  • -x 在第一个测试失败时退出,

  • --lf 重新运行上次运行中失败的测试,

  • --ff 重新运行所有先前的测试,首先运行失败的测试,

  • -s 使 pytest 不捕获 print() 语句的输出,

  • --tb=short--tb=line 控制日志的长度,

  • --runxfail 还运行标记为已知失败 (XFAIL) 的测试并报告错误。

由于我们的持续集成测试如果 FutureWarning 未被正确捕获,则会出错,因此建议在使用 -Werror::FutureWarning 标志的同时运行 pytest

审查的标准回复#

将其中一些存储在 GitHub 的 保存的回复 中以供审查可能会有所帮助

问题:使用问题

You are asking a usage question. The issue tracker is for bugs and new features. For usage questions, it is recommended to try [Stack Overflow](https://stackoverflow.com/questions/tagged/scikit-learn) or [the Mailing List](https://mail.python.org/mailman/listinfo/scikit-learn).

Unfortunately, we need to close this issue as this issue tracker is a communication tool used for the development of scikit-learn. The additional activity created by usage questions crowds it too much and impedes this development. The conversation can continue here, however there is no guarantee that it will receive attention from core developers.

问题:欢迎您更新文档

Please feel free to offer a pull request updating the documentation if you feel it could be improved.

问题:错误的自包含示例

Please provide [self-contained example code](https://scikit-learn.cn/dev/developers/minimal_reproducer.html), including imports and data (if possible), so that other contributors can just run it and reproduce your issue. Ideally your example code should be minimal.

问题:软件版本

To help diagnose your issue, please paste the output of:
```py
import sklearn; sklearn.show_versions()
```
Thanks.

问题:代码块

Readability can be greatly improved if you [format](https://help.github.com/articles/creating-and-highlighting-code-blocks/) your code snippets and complete error messages appropriately. For example:

    ```python
    print(something)
    ```

generates:

```python
print(something)
```

And:

    ```pytb
    Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
    ImportError: No module named 'hello'
    ```

generates:

```pytb
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
ImportError: No module named 'hello'
```

You can edit your issue descriptions and comments at any time to improve readability. This helps maintainers a lot. Thanks!

问题/评论:链接到代码

Friendly advice: for clarity's sake, you can link to code like [this](https://help.github.com/articles/creating-a-permanent-link-to-a-code-snippet/).

问题/评论:链接到评论

Please use links to comments, which make it a lot easier to see what you are referring to, rather than just linking to the issue. See [this](https://stackoverflow.com/questions/25163598/how-do-i-reference-a-specific-issue-comment-on-github) for more details.

PR-NEW:更好的描述和标题

Thanks for the pull request! Please make the title of the PR more descriptive. The title will become the commit message when this is merged. You should state what issue (or PR) it fixes/resolves in the description using the syntax described [here](https://scikit-learn.cn/dev/developers/contributing.html#contributing-pull-requests).

PR-NEW:修复 #

Please use "Fix #issueNumber" in your PR description (and you can do it more than once). This way the associated issue gets closed automatically when the PR is merged. For more details, look at [this](https://github.com/blog/1506-closing-issues-via-pull-requests).

PR-NEW 或 问题:维护成本

Every feature we include has a [maintenance cost](https://scikit-learn.cn/dev/faq.html#why-are-you-so-selective-on-what-algorithms-you-include-in-scikit-learn). Our maintainers are mostly volunteers. For a new feature to be included, we need evidence that it is often useful and, ideally, [well-established](https://scikit-learn.cn/dev/faq.html#what-are-the-inclusion-criteria-for-new-algorithms) in the literature or in practice. Also, we expect PR authors to take part in the maintenance for the code they submit, at least initially. That doesn't stop you implementing it for yourself and publishing it in a separate repository, or even [scikit-learn-contrib](https://scikit-learn-contrib.github.io).

PR-WIP:合并之前需要什么?

Please clarify (perhaps as a TODO list in the PR description) what work you believe still needs to be done before it can be reviewed for merge. When it is ready, please prefix the PR title with `[MRG]`.

PR-WIP:需要回归测试

Please add a [non-regression test](https://en.wikipedia.org/wiki/Non-regression_testing) that would fail at main but pass in this PR.

PR-WIP:PEP8

You have some [PEP8](https://www.pythonlang.cn/dev/peps/pep-0008/) violations, whose details you can see in the Circle CI `lint` job. It might be worth configuring your code editor to check for such errors on the fly, so you can catch them before committing.

PR-MRG:耐心

Before merging, we generally require two core developers to agree that your pull request is desirable and ready. [Please be patient](https://scikit-learn.cn/dev/faq.html#why-is-my-pull-request-not-getting-any-attention), as we mostly rely on volunteered time from busy core developers. (You are also welcome to help us out with [reviewing other PRs](https://scikit-learn.cn/dev/developers/contributing.html#code-review-guidelines).)

PR-MRG:添加到新增功能中

Please add an entry to the change log at `doc/whats_new/v*.rst`. Like the other entries there, please reference this pull request with `:pr:` and credit yourself (and other contributors if applicable) with `:user:`.

PR:不要更改无关内容

Please do not change unrelated lines. It makes your contribution harder to review and may introduce merge conflicts to other pull requests.

使用 valgrind 调试 Cython 中的内存错误#

虽然 python/numpy 的内置内存管理相对健壮,但它会导致某些例程的性能下降。出于这个原因,scikit-learn 中的大部分高性能代码都是用 cython 编写的。但是,这种性能提升也带来了权衡:在 cython 代码中,尤其是在代码严重依赖指针运算的情况下,内存错误很容易出现。

内存错误可以通过多种方式表现出来。最容易调试的通常是段错误和相关的 glibc 错误。未初始化的变量会导致难以追踪的意外行为。调试此类错误时,一个非常有用的工具是 valgrind

Valgrind 是一个命令行工具,可以跟踪各种代码中的内存错误。请按照以下步骤操作

  1. 在您的系统上安装 valgrind

  2. 下载 python valgrind 抑制文件:valgrind-python.supp

  3. 按照 README.valgrind 文件中的说明自定义您的 python 抑制。如果您不这样做,您将收到来自 python 解释器而不是您自己的代码的虚假输出。

  4. 按如下方式运行 valgrind

    valgrind -v --suppressions=valgrind-python.supp python my_test_script.py
    

结果将是所有与内存相关的错误的列表,这些错误引用了 cython 从您的 .pyx 文件生成的 C 代码中的行。如果您检查 .c 文件中引用的行,您将看到指示您 .pyx 源文件中的相应位置的注释。希望输出能为您提供有关内存错误来源的线索。

有关 valgrind 及其各种选项的更多信息,请参阅 valgrind 网站 上的教程和文档。

在 x86_64 机器上为 ARM64 平台构建和测试#

基于 ARM 的机器是移动、边缘或其他低能耗部署(包括云,例如在 Scaleway 或 AWS Graviton 上)的热门目标。

以下是在 x86_64 主机笔记本电脑或工作站上设置本地开发环境以重现 ARM 特定错误或测试失败的说明。这基于使用 docker 为了方便起见而进行的 QEMU 用户模式仿真(请参阅 multiarch/qemu-user-static)。

注意

以下说明针对 ARM64,但它们也适用于 ppc64le,只需相应地更改 Docker 镜像和 Miniforge 路径。

在主机文件系统上准备一个文件夹,并下载必要的工具和源代码。

mkdir arm64
pushd arm64
wget https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-aarch64.sh
git clone https://github.com/scikit-learn/scikit-learn.git

使用 docker 安装 QEMU 用户模式,并运行一个 ARM64v8 容器,该容器可以访问您共享文件夹下的 /io 挂载点。

docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
docker run -v`pwd`:/io --rm -it arm64v8/ubuntu /bin/bash

在容器中,为 ARM64(又名 aarch64)架构安装 miniforge3。

bash Miniforge3-Linux-aarch64.sh
# Choose to install miniforge3 under: `/io/miniforge3`

每次重新启动新容器时,您都需要重新初始化之前安装在 /io/miniforge3 下的 conda 环境。

/io/miniforge3/bin/conda init
source /root/.bashrc

因为 /root 主文件夹是短暂的 docker 容器的一部分。另一方面,存储在 /io 下的每个文件或目录都是持久的。

然后,您可以像往常一样构建 scikit-learn(您需要使用 apt 或 conda 像往常一样安装编译器工具和依赖项)。由于仿真层,构建 scikit-learn 需要很长时间,但是如果您将 scikit-learn 文件夹放在 /io 挂载点下,则只需要执行一次。

然后使用 pytest 仅运行您感兴趣的模块的测试。

Meson 构建后端#

从 scikit-learn 1.5.0 开始,我们使用 meson-python 作为构建工具。Meson 是 scikit-learn 和 PyData 生态系统的新工具。它被其他几个软件包使用,这些软件包已经编写了关于它是什么以及它是如何工作的良好指南。