Entwickler-Tipps und Tricks#

Tipps zur Steigerung der Produktivität und zur Erhaltung der geistigen Gesundheit#

In diesem Abschnitt sammeln wir einige nützliche Ratschläge und Werkzeuge, die Ihre Lebensqualität bei der Überprüfung von Pull-Anfragen, der Ausführung von Unit-Tests usw. erhöhen können. Einige dieser Tricks bestehen aus User-Skripten, die eine Browser-Erweiterung wie TamperMonkey oder GreaseMonkey erfordern; um User-Skripte einzurichten, müssen Sie eine dieser Erweiterungen installiert, aktiviert und ausgeführt haben. Wir stellen User-Skripte als GitHub Gists bereit; um sie zu installieren, klicken Sie auf die Schaltfläche "Raw" auf der Gist-Seite.

Ausblenden und Einblenden veralteter Diffs in Pull-Anfragen#

GitHub verbirgt Diskussionen in PRs, wenn die entsprechenden Codezeilen inzwischen geändert wurden. Dieses Userscript bietet eine Verknüpfung (zum Zeitpunkt der Erstellung Strg-Alt-P, aber schauen Sie in den Code, um sicher zu gehen), um alle derartigen versteckten Diskussionen auf einmal einzublenden, damit Sie auf dem Laufenden bleiben.

Pull-Anfragen als Remote-Tracking-Branches auschecken#

Fügen Sie in Ihrem lokalen Fork unter der Überschrift [remote "upstream"] in Ihrer .git/config die Zeile hinzu:

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

Sie können dann git checkout pr/PR_NUMBER verwenden, um zum Code der Pull-Anfrage mit der angegebenen Nummer zu navigieren. (Mehr dazu in diesem Gist.)

Code-Coverage in Pull-Anfragen anzeigen#

Um die von der CodeCov Continuous Integration generierten Code-Coverage-Berichte zu überlagern, ziehen Sie diese Browser-Erweiterung in Betracht. Die Abdeckung jeder Zeile wird als farbiger Hintergrund hinter der Zeilennummer angezeigt.

Nützliche pytest-Aliase und Flags#

Die vollständige Testsuite dauert ziemlich lange. Für schnellere Iterationen ist es möglich, eine Teilmenge von Tests mit pytest-Selektoren auszuwählen. Insbesondere kann man einen einzelnen Test anhand seiner Node-ID ausführen

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

oder den -k pytest-Parameter verwenden, um Tests anhand ihres Namens auszuwählen. Zum Beispiel,

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

führt alle gemeinsamen Tests für den LogisticRegression Schätzer aus.

Wenn ein Unit-Test fehlschlägt, können die folgenden Tricks das Debugging erleichtern

  1. Das Kommandozeilenargument pytest -l weist pytest an, die lokalen Variablen bei einem Fehler auszugeben.

  2. Das Argument pytest --pdb springt bei einem Fehler in den Python-Debugger. Um stattdessen in den erweiterten IPython-Debugger ipdb zu springen, können Sie einen Shell-Alias einrichten für

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

Andere pytest Optionen, die nützlich werden könnten, sind

  • -x, womit beim ersten fehlerhaften Test beendet wird,

  • --lf, um die Tests, die beim vorherigen Lauf fehlgeschlagen sind, erneut auszuführen,

  • --ff, um alle vorherigen Tests erneut auszuführen und dabei zuerst die fehlerhaften Tests auszuführen,

  • -s, damit pytest die Ausgabe von print()-Anweisungen nicht abfängt,

  • --tb=short oder --tb=line, um die Länge der Logs zu steuern,

  • --runxfail, um auch Tests auszuführen, die als bekannter Fehler (XFAIL) markiert sind, und Fehler zu melden.

Da unsere Continuous Integration Tests fehlschlagen, wenn FutureWarning nicht ordnungsgemäß abgefangen wird, wird auch empfohlen, pytest zusammen mit dem Flag -Werror::FutureWarning auszuführen.

Standardantworten für die Überprüfung#

Es kann hilfreich sein, einige davon in den gespeicherten Antworten von GitHub für die Überprüfung zu speichern

Problem: Nutzungsfragen

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.

Problem: Sie können gerne die Dokumentation aktualisieren

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

Problem: Eigenständiges Beispiel für einen Fehler

Please provide [self-contained example code](https://scikit-learn.de/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.

Problem: Softwareversionen

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

Problem: Codeblöcke

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!

Problem/Kommentar: Verknüpfung zu Code

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/).

Problem/Kommentar: Verknüpfung zu Kommentaren

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-NEU: Bessere Beschreibung und Titel

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.de/dev/developers/contributing.html#contributing-pull-requests).

PR-NEU: Behebt #

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).

Problem/PR: Wartungskosten

Every feature we include has a [maintenance cost](https://scikit-learn.de/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.de/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-ARBEIT: Was ist vor dem Mergen nötig?

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-ARBEIT: Regressionstest erforderlich

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-FERTIG: Geduld

Before merging, we generally require two core developers to agree that your pull request is desirable and ready. [Please be patient](https://scikit-learn.de/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.de/dev/developers/contributing.html#code-review-guidelines).)

PR-FERTIG: Zu den Neuigkeiten hinzufügen

Please add an entry to the future changelog by adding an RST fragment into the module associated with your change located in `doc/whats_new/upcoming_changes`. Refer to the following [README](https://github.com/scikit-learn/scikit-learn/blob/main/doc/whats_new/upcoming_changes/README.md) for full instructions.

PR: Nichts Unverbundenes ändern

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

Debugging von CI-Problemen#

CI-Probleme können aus einer Vielzahl von Gründen auftreten, daher ist dies keineswegs ein umfassender Leitfaden, sondern vielmehr eine Liste nützlicher Tipps und Tricks.

Verwendung einer Lock-Datei, um eine Umgebung zu erhalten, die der CI ähnelt#

conda-lock kann verwendet werden, um eine Conda-Umgebung mit exakt denselben Conda- und Pip-Paketen wie auf der CI zu erstellen. Zum Beispiel erstellt der folgende Befehl eine Conda-Umgebung namens scikit-learn-doc, die der CI ähnelt

conda-lock install -n scikit-learn-doc build_tools/circle/doc_linux-64_conda.lock

Hinweis

Dies funktioniert nur, wenn Sie dasselbe Betriebssystem wie die CI-Build haben (prüfen Sie platform: in der Lock-Datei). Zum Beispiel funktioniert der vorherige Befehl nur, wenn Sie auf einem Linux-Rechner sind. Außerdem können dadurch einige Probleme, die stärker an die Besonderheiten der CI-Umgebung gebunden sind, nicht reproduziert werden, z. B. die von OpenBLAS in sklearn.show_versions() gemeldete CPU-Architektur.

Wenn Sie nicht dasselbe Betriebssystem wie die CI-Build haben, können Sie trotzdem eine Conda-Umgebung aus der richtigen Umgebungs-YAML-Datei erstellen, obwohl sie nicht so nah an der CI-Umgebung sein wird wie die Verwendung der zugehörigen Lock-Datei. Zum Beispiel für den Dokumentations-Build

conda env create -n scikit-learn-doc -f build_tools/circle/doc_environment.yml -y

Dies liefert möglicherweise nicht exakt dieselben Paketversionen wie in der CI aus verschiedenen Gründen, zum Beispiel

  • einige Pakete hatten möglicherweise neue Versionen zwischen der letzten Aktualisierung der Lock-Dateien im main-Branch und dem Zeitpunkt, an dem Sie den Befehl conda create ausführen. Sie können immer versuchen, die Version in der Lock-Datei nachzuschauen und die Versionen manuell für bestimmte Pakete anzugeben, von denen Sie denken, dass sie bei der Reproduktion des Problems helfen würden.

  • verschiedene Pakete werden je nach Betriebssystem standardmäßig installiert. Zum Beispiel ist die Standard-BLAS-Bibliothek bei der Installation von NumPy OpenBLAS unter Linux und MKL unter Windows.

Auch das Problem kann betriebssystemspezifisch sein, so dass die einzige Möglichkeit, es zu reproduzieren, darin besteht, dasselbe Betriebssystem wie die CI-Build zu haben.

Debugging von Speicherfehlern in Cython mit Valgrind#

Während das integrierte Speichermanagement von Python/NumPy relativ robust ist, kann es bei einigen Routinen zu Leistungseinbußen führen. Aus diesem Grund ist ein Großteil des Hochleistungscodes in scikit-learn in Cython geschrieben. Diese Leistungssteigerung hat jedoch einen Kompromiss: Speicherfehler können leicht in Cython-Code auftreten, insbesondere in Situationen, in denen dieser Code stark auf Zeigerarithmetik angewiesen ist.

Speicherfehler können sich auf verschiedene Weise manifestieren. Die am einfachsten zu debuggenden sind oft Segmentierungsfehler und verwandte glibc-Fehler. Uninitialisierte Variablen können zu unerwartetem Verhalten führen, das schwer zu verfolgen ist. Ein sehr nützliches Werkzeug beim Debugging dieser Art von Fehlern ist Valgrind.

Valgrind ist ein Kommandozeilenwerkzeug, das Speicherfehler in einer Vielzahl von Codes verfolgen kann. Befolgen Sie diese Schritte

  1. Installieren Sie Valgrind auf Ihrem System.

  2. Laden Sie die Python Valgrind Suppression-Datei herunter: valgrind-python.supp.

  3. Befolgen Sie die Anweisungen in der Datei README.valgrind, um Ihre Python-Suppressions anzupassen. Andernfalls erhalten Sie eine irreführende Ausgabe im Zusammenhang mit dem Python-Interpreter anstelle Ihres eigenen Codes.

  4. Führen Sie Valgrind wie folgt aus

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

Das Ergebnis ist eine Liste aller speicherbezogenen Fehler, die sich auf Zeilen im C-Code beziehen, der von Cython aus Ihrer .pyx-Datei generiert wurde. Wenn Sie die referenzierten Zeilen in der .c-Datei untersuchen, sehen Sie Kommentare, die die entsprechende Stelle in Ihrer .pyx-Quelldatei angeben. Hoffentlich gibt die Ausgabe Hinweise auf die Ursache Ihres Speicherfehlers.

Weitere Informationen zu Valgrind und den verfügbaren Optionen finden Sie in den Tutorials und der Dokumentation auf der Valgrind-Website.

Erstellung und Test für die ARM64-Plattform auf einem x86_64-Rechner#

ARM-basierte Maschinen sind ein beliebtes Ziel für mobile, Edge- oder andere energieeffiziente Einsätze (einschließlich in der Cloud, z. B. auf Scaleway oder AWS Graviton).

Hier sind Anweisungen zur Einrichtung einer lokalen Entwicklungsumgebung, um ARM-spezifische Fehler oder Testfehler auf einem x86_64 Host-Laptop oder -Arbeitsplatz zu reproduzieren. Dies basiert auf der QEMU-Benutzermodus-Emulation mit Docker zur Bequemlichkeit (siehe multiarch/qemu-user-static).

Hinweis

Die folgenden Anweisungen sind für ARM64 illustriert, gelten aber auch für ppc64le, nachdem das Docker-Image und die Miniforge-Pfade entsprechend geändert wurden.

Bereiten Sie einen Ordner auf dem Host-Dateisystem vor und laden Sie die notwendigen Werkzeuge und den Quellcode herunter

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

Verwenden Sie Docker, um den QEMU-Benutzermodus zu installieren und einen ARM64v8-Container auszuführen, der Zugriff auf Ihren freigegebenen Ordner unter dem /io Mountpunkt hat

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

Im Container installieren Sie miniforge3 für die ARM64 (auch bekannt als aarch64) Architektur

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

Jedes Mal, wenn Sie einen neuen Container neu starten, müssen Sie die zuvor unter /io/miniforge3 installierte Conda-Umgebung neu initialisieren

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

da der Home-Ordner /root Teil des ephemeren Docker-Containers ist. Jede Datei oder jedes Verzeichnis, das unter /io gespeichert ist, ist dagegen persistent.

Sie können dann scikit-learn wie gewohnt erstellen (Sie müssen Compiler-Tools und Abhängigkeiten wie üblich mit apt oder conda installieren). Das Erstellen von scikit-learn dauert aufgrund der Emulationsschicht sehr lange, muss aber nur einmal durchgeführt werden, wenn Sie den scikit-learn-Ordner unter dem Mountpunkt /io ablegen.

Verwenden Sie dann pytest, um nur die Tests des Moduls auszuführen, an dessen Debugging Sie interessiert sind.

Das Meson Build Backend#

Seit scikit-learn 1.5.0 verwenden wir meson-python als Build-Tool. Meson ist ein neues Tool für scikit-learn und das PyData-Ökosystem. Es wird von mehreren anderen Paketen verwendet, die gute Anleitungen dazu geschrieben haben, was es ist und wie es funktioniert.

  • pandas Setup Doc: pandas hat ein ähnliches Setup wie wir (kein Spin oder dev.py)

  • scipy Meson Doc gibt mehr Hintergrundinformationen darüber, wie Meson hinter den Kulissen funktioniert.