Files
2026-03-27 12:58:01 +01:00

525 lines
12 KiB
Markdown
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Hier eine umfassende, aber für Einsteiger verständliche Einführung in **black**, den „opinionated“ Python-Code-Formatter.
---
## 1. Grundidee von *black*
**Was ist black?**
- *black* ist ein **automatisches Formatierungs-Tool** für Python.
- Es ändert **nur die Formatierung**, nicht die Logik deines Codes.
- Es ist **„opinionated“**: Es gibt nur sehr wenige Einstellungen black entscheidet den Stil für dich.
**Zentrale Idee:**
> „*You are not your code style.*“
> Statt darüber zu diskutieren, ob ein Leerzeichen hier oder dort besser ist, überlässt du das black.
>
> Ziel:
> - einheitlicher Stil
> - weniger Diskussionen in Code Reviews
> - Fokus auf inhaltliche Fehler, nicht auf Formatierung
---
## 2. Was macht black konkret?
Black nimmt deinen Python-Code, parst ihn und schreibt ihn nach festen Regeln neu. Beispiele:
### 2.1 Installation
```bash
pip install black
```
### 2.2 Einfache Nutzung
Eine einzelne Datei formatieren:
```bash
black main.py
```
Ein ganzes Projekt:
```bash
black .
```
Nur anzeigen, was geändert würde (ohne zu schreiben):
```bash
black --diff --check .
```
---
## 3. Praxisnahe Formatierungsbeispiele
### 3.1 Zeilenumbrüche und Einrückung
**Vorher:**
```python
def very_long_function_name(arg1,arg2,arg3,arg4,arg5,arg6,arg7=False,arg8=None):
return (arg1+arg2+arg3+arg4+arg5+arg6)
```
**Nachher (black):**
```python
def very_long_function_name(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7=False,
arg8=None,
):
return arg1 + arg2 + arg3 + arg4 + arg5 + arg6
```
Was passiert?
- Argumente werden sauber untereinander geschrieben.
- Operatoren (+) werden mit Leerzeichen versehen.
- Abschluss-Komma nach dem letzten Argument (hilft bei späteren Änderungen).
---
### 3.2 Strings und Anführungszeichen
Black bevorzugt fast immer **doppelte Anführungszeichen**.
**Vorher:**
```python
name = 'Alice'
message = 'Hello, ' + name + '!'
```
**Nachher:**
```python
name = "Alice"
message = "Hello, " + name + "!"
```
Ausnahmen:
- Wenn ein String doppelte Anführungszeichen enthält, kann black einzelne beibehalten, um weniger zu escapen.
---
### 3.3 Leerzeichen und Klammern
**Vorher:**
```python
result=(1+2)*3
if x==42:
print( 'Answer',x )
```
**Nachher:**
```python
result = (1 + 2) * 3
if x == 42:
print("Answer", x)
```
Black:
- fügt Leerzeichen um Operatoren hinzu (`1 + 2`, `x == 42`),
- entfernt unnötige Leerzeichen (`print( 'Answer',x )``print("Answer", x)`).
---
### 3.4 Collections (Listen, Dicts, Sets)
**Vorher:**
```python
config = {"host":"localhost","port":5432,"debug":True}
```
**Nachher:**
```python
config = {
"host": "localhost",
"port": 5432,
"debug": True,
}
```
Vorteile:
- Bessere Lesbarkeit
- Leicht, neue Einträge hinzuzufügen (wegen Abschluss-Komma).
---
### 3.5 Lange Ausdrücke
**Vorher:**
```python
query = session.query(User).filter(User.is_active==True, User.signup_date>=start_date, User.signup_date<=end_date).order_by(User.signup_date.desc())
```
**Nachher:**
```python
query = (
session.query(User)
.filter(
User.is_active == True,
User.signup_date >= start_date,
User.signup_date <= end_date,
)
.order_by(User.signup_date.desc())
)
```
Black bricht lange Zeilen so um, dass:
- sie unter der vorgegebenen Maximalbreite bleiben (standard: 88 Zeichen),
- die Struktur des Codes klarer sichtbar wird.
---
## 4. Abgrenzung zu verwandten Tools
### 4.1 Formatter vs. Linter vs. Typprüfer
- **Formatter** (Formatierer):
Passen das **Aussehen** deines Codes an z.B. black, autopep8, yapf.
- **Linter**:
Finden mögliche **Fehler, Stilprobleme oder unschöne Konstrukte** z.B. flake8, pylint, ruff.
- **Typprüfer**:
Prüfen, ob Typen konsistent sind (z.B. mit `typing`) z.B. mypy, pyright.
Black ist **nur** ein Formatter.
---
### 4.2 Black vs. autopep8
**autopep8**:
- Ziel: Code so anpassen, dass er PEP8-konform ist.
- Orientierung direkt an den PEP8-Regeln.
- Viele Optionen (z.B. bestimmte Checks an- oder abschalten).
**black**:
- Ziel: **konsequenter, einheitlicher Stil** nicht nur PEP8, sondern zusätzliche strenge Regeln.
- Sehr wenige Konfigurationsmöglichkeiten (bewusst!).
- Output ist oft deutlich „strenger” und einheitlicher als autopep8.
---
### 4.3 Black vs. yapf
**yapf**:
- Google-Tool zur Formatierung von Python.
- Sehr konfigurierbar: du kannst deinen Style stark beeinflussen (ähnlich wie bei C++/clang-format).
- Mehr Freiheit, aber dadurch auch mehr Diskussionen möglich.
**black**:
- „Meine Regeln oder gar nicht“.
- Ziel: Diskussionen vermeiden, daher kaum Konfigurationsoptionen.
- Sehr stabiler, vorhersehbarer Output.
---
### 4.4 Black vs. isort
**isort** ist ein Tool, um **Imports** zu sortieren und zu gruppieren.
- Sortiert `import`-Zeilen alphabetisch und nach Gruppen:
- Standardbibliothek
- Third-Party
- Projektinterne Module
Black:
- Formatiert auch Imports (Zeilenumbrüche, Leerzeichen),
- sortiert sie aber **nicht** nach Paketnamen.
Typischerweise nutzt man:
```bash
isort .
black .
```
Oder beides zusammen über Tools wie `ruff` oder `pre-commit`.
---
## 5. Welche Probleme löst black?
### 5.1 Konsistenter Stil in Teams
Ohne Tool:
- Jeder schreibt „sein“ Python.
- Unterschiedliche Leerzeichen, Umbrüche, String-Stile, etc.
- Code wirkt „bunt“ und uneinheitlich.
Mit black:
- Jedes Commit, jede Datei, jede Funktion hat denselben Stil.
- Neue Teammitglieder lernen schneller, was „üblich“ ist es ist einfach: das, was black macht.
---
### 5.2 Weniger Diskussionen in Code Reviews
Vor black:
- Kommentare wie: „Bitte hier ein Leerzeichen einfügen.“
- „Kannst du die Argumente untereinander schreiben?“
- „Wir verwenden eigentlich doppelte Anführungszeichen.“
Mit black:
- Reviewer sagen: „Bitte einmal black drüber laufen lassen.“
- Fokus liegt auf:
- Ist der Algorithmus korrekt?
- Sind die Funktionen gut benannt?
- Sind Tests vorhanden?
---
### 5.3 Bessere Lesbarkeit & Wartbarkeit
- Lange Zeilen werden sinnvoll umgebrochen.
- Verschachtelte Ausdrücke werden strukturiert.
- Datensammlungen (Listen, Dicts) werden mehrzeilig und übersichtlich dargestellt.
Beispiel: Eine unübersichtliche Dict-Liste wird automatisch gut lesbar formatiert.
**Vorher:**
```python
users=[{"id":1,"name":"Alice","active":True},{"id":2,"name":"Bob","active":False}]
```
**Nachher:**
```python
users = [
{"id": 1, "name": "Alice", "active": True},
{"id": 2, "name": "Bob", "active": False},
]
```
---
### 5.4 Weniger „Rauschen“ in Git-Diffs
Manuell Änderungen + Formatierung:
- Du änderst eine Zeile, formatierst etwas,
- der Diff zeigt viele Änderungen, obwohl nur wenig Logik geändert wurde.
Mit black:
- Wenn alle Dateien bereits formatiert sind, entstehen bei späteren Änderungen klarere Diffs:
- Format ist überall gleich,
- nur die wirklich geänderte Logik fällt auf.
---
## 6. Herausforderungen und typische Stolpersteine
### 6.1 Einstieg in ein bestehendes Projekt
Problem:
- Du führst black in einem **alten, großen Projekt** ein.
- Beim ersten Durchlauf ändert black Hunderte/tausende Dateien.
- Git-Diff ist riesig.
Lösungen / Best Practices:
- Einmaliger „Formatting-Commit“ (nur Style):
- In einem eigenen Commit alle Dateien mit black formatieren.
- Danach neue Commits nur mit funktionalen Anpassungen.
- Oder schrittweise:
- Nur neue/aktuell bearbeitete Module mit black formatieren.
- z.B. mit `pre-commit`-Hook nur geänderte Dateien behandeln.
---
### 6.2 „Mir gefällt der Stil nicht!“
Black ist sehr strikt:
- Du kannst nicht „mal eben“ sagen:
- „Ich möchte lieber 120 statt 88 Zeichen pro Zeile“ (ok, das **geht** als Option)
- Aber: Du kannst nicht festlegen, wie exakt bestimmte Konstrukte formatiert werden.
Beispiel: Viele stören sich zunächst an:
- doppelten Anführungszeichen,
- „ungewöhnlichen“ Zeilenumbrüchen.
Wichtig:
- black ist ein **Team-Tool**.
- Man einigt sich darauf, den Stil zu akzeptieren, um Diskussionen zu vermeiden.
---
### 6.3 Integration mit anderen Tools (z.B. isort, flake8, ruff)
Typische Stolperfallen:
- `isort` und `black` können sich widersprechen, wenn sie unterschiedliche Maximalzeilenlängen nutzen.
- Linter können sich über Formatierung beschweren, wenn sie anders konfiguriert sind als black.
Best Practice:
- Einheitliche Konfiguration, z.B. in `pyproject.toml`:
```toml
[tool.black]
line-length = 88
[tool.isort]
profile = "black"
line_length = 88
```
So passen Formatierung und Importsortierung zusammen.
---
### 6.4 Änderungen zwischen Black-Versionen
Black entwickelt sich weiter.
- In seltenen Fällen ändert eine neue Version den Stil leicht.
- Dann kann ein erneuter Durchlauf große Diffs erzeugen.
Abhilfe:
- Black-Version in `pyproject.toml` oder `requirements.txt` fest pinnen:
```text
black==24.4.2
```
- Gelegentlich bewusst aktualisieren und einmaliger Reformatting-Commit.
---
### 6.5 Performance bei sehr großen Projekten
Für normale Projekte ist black schnell genug.
Bei **sehr großen Repositories** kann einmaliges Formatieren aber dauern.
Lösungen:
- Nur geänderte Dateien formatieren (z.B. über `pre-commit`).
- In CI nur `black --check .` laufen lassen (prüft, ob alles formatiert ist, ohne neu zu schreiben).
---
## 7. Black in der Praxis: Workflows
### 7.1 Integration in den Editor/IDE
Die meisten Editoren können black beim Speichern ausführen:
- **VS Code**:
- Erweiterung „Python“ installieren.
- In `settings.json`:
```json
{
"python.formatting.provider": "black",
"editor.formatOnSave": true
}
```
- **PyCharm**:
- Externes Tool konfigurieren oder über Plugins.
Vorteil:
- Du denkst nicht mehr über Formatierung nach: Speichern = fertig formatiert.
---
### 7.2 Verwendung mit `pre-commit`
`pre-commit` ist ein Tool, das Skripte ausführt, bevor ein Git-Commit akzeptiert wird.
Installieren:
```bash
pip install pre-commit
```
In `.pre-commit-config.yaml`:
```yaml
repos:
- repo: https://github.com/psf/black
rev: 24.4.2 # Version anpassen
hooks:
- id: black
```
Aktivieren:
```bash
pre-commit install
```
Jetzt wird bei jedem `git commit` black auf die geänderten Dateien angewandt.
Das stellt sicher, dass alles im Repo immer formatiert ist.
---
### 7.3 Black in der CI-Pipeline
In CI-Systemen (GitHub Actions, GitLab CI, etc.) kannst du prüfen, ob der Code schon formatiert ist.
Beispiel (CLI):
```bash
black --check .
```
- Exit-Code 0: alles ok.
- Exit-Code ≠ 0: irgendetwas müsste formatiert werden.
Das verhindert, dass unformatierter Code in `main` oder `master` landet.
---
## 8. Zusammenfassung
- **black** ist ein **sehr strenger, kaum konfigurierbarer Formatter** für Python-Code.
- Ziel:
- **einheitlicher Stil**,
- **keine Diskussionen** über Formatierung,
- Fokus auf Logik und Qualität statt auf Leerzeichen.
- Abgrenzung:
- black formatiert nur es ist kein Linter und kein Typprüfer.
- Im Vergleich zu autopep8/yapf: weniger konfigurierbar, dafür klarer, einheitlicher Stil.
- Es löst:
- Stil-Inkonsistenz, Formatierungs-Diskussionen, „Rauschen“ in Diffs.
- Herausforderungen:
- Einstieg in ältere Projekte,
- wenig Einfluss auf Stil,
- Abstimmung mit anderen Tools, Versionsänderungen.
- In der Praxis:
- Nutze black im Editor (Format-on-save),
- im `pre-commit`-Hook,
- und als `--check` in der CI.
Wenn du möchtest, kann ich dir im nächsten Schritt ein kleines Beispielprojekt konstruieren (mit `pyproject.toml`, `pre-commit`, isort/black-Konfiguration), damit du siehst, wie man black von Anfang an sauber einrichtet.