add synced notes on IT know how

This commit is contained in:
Mathias Schneider
2026-03-17 19:01:50 +01:00
parent b8797d5ca8
commit fc3aef4da8
31 changed files with 13162 additions and 1 deletions
+540
View File
@@ -0,0 +1,540 @@
Ruff ist ein relativ neues, sehr schnelles Tool zur Verbesserung der Code-Qualität in Python. Es kombiniert Funktionen, für die man früher mehrere Werkzeuge brauchte (Linter, Formatter, Import-Sortierer, teilweise Sicherheits-Checks), in einem Programm.
Ich gehe Schritt für Schritt durch:
1. Grundidee und Zielgruppe
2. Was macht ruff konkret?
3. Abgrenzung zu ähnlichen Tools
4. Welche Probleme löst ruff?
5. Typische Herausforderungen im Einsatz
6. Praxisnahe Beispiele (inkl. Konfiguration)
---
## 1. Grundidee von ruff in einfachen Worten
Stell dir vor, mehrere Entwickler:innen arbeiten an einem Python-Projekt. Ohne Regeln sieht der Code schnell sehr unterschiedlich aus:
- Mal sind Leerzeichen anders gesetzt,
- mal werden nicht genutzte Variablen liegen gelassen,
- vielleicht wird an manchen Stellen unsicherer Code geschrieben,
- im schlimmsten Fall fallen bestimmte Fehler erst spät auf.
Bisher nutzte man typischerweise mehrere Tools:
- ein **Linter** (z.B. *flake8* oder *pylint*),
- einen **Formatter** (z.B. *black*),
- einen **Import-Sortierer** (z.B. *isort*),
- evtl. ein **Security-Tool** (z.B. *bandit*),
- plus diverse Plugins.
**Ruff will das bündeln:**
- Ein Tool für viele Code-Qualitätsaspekte
- Sehr schnell (geschrieben in Rust, nicht in Python)
- Einfache Konfiguration (alles typischerweise in `pyproject.toml`)
- Viele Checks, die sich an bekannten Tools orientieren (flake8-Plugins, isort-Regeln, bandit-Regeln usw.)
---
## 2. Was macht ruff konkret?
### 2.1. Linting (Fehler und Stilprobleme finden)
Ruff untersucht deinen Python-Code und meldet z.B.:
- Syntax-Fehler
- Ungenutzte Variablen oder Importe
- Logische Stolperfallen (z.B. `== None` statt `is None`)
- Stil-Regeln (z.B. maximale Zeilenlänge)
- Potenziell unsichere Konstruktionen
Beispiel:
```python
def calculate(a, b):
result = a + b
unused = 42
if a == None:
print("a is None")
return result
```
Ruff würde in etwa melden (vereinfacht):
- `unused` wird nie verwendet
- `a == None` besser `a is None`
Viele dieser Probleme kann ruff auch **automatisch beheben** (`--fix`).
---
### 2.2. Formatierung (Code automatisch „schön“ machen)
Ruff hat inzwischen einen **eigenen Formatter**, der ähnlich wie *black* funktioniert:
- Einheitliche Einrückungen und Zeilenumbrüche
- Klammer-Formatierung
- Konsistente Verwendung von Anführungszeichen (je nach Einstellung)
- Entfernung überflüssiger Leerzeilen usw.
Beispiel (unformatierter Code):
```python
def foo( x:int,y:int )->int:
return x+y
```
Nach `ruff format` könnte das so aussehen:
```python
def foo(x: int, y: int) -> int:
return x + y
```
---
### 2.3. Imports sortieren und aufräumen
Ruff kann ähnlich wie *isort*:
- Importe sortieren (alphabetisch und nach Gruppen: Standardbibliothek, Drittanbieter, Projektcode)
- Unbenutzte Importe entfernen
Beispiel:
```python
import myproject.utils
import os
import sys
import requests
from math import sqrt
from math import ceil
```
Nach ruff (vereinfacht):
```python
import os
import sys
from math import ceil, sqrt
import requests
import myproject.utils
```
Und wenn `sys` gar nicht verwendet wird, kann ruff es auch entfernen.
---
### 2.4. Ein Tool mehrere Regel-Sammlungen
Ruff bringt rule sets mit, die vielen bekannten Tools entsprechen, z.B.:
- **E/F/W**: Pycodestyle/Pyflakes-ähnlich (via flake8)
- **I**: isort-Regeln
- **N**: pep8-naming (Namenskonventionen)
- **S**: bandit (Sicherheitsregeln)
- **UP**: pyupgrade (veraltete Syntax, modernisieren)
- u.v.m.
Du kannst über die Konfiguration steuern, welche Regel-Gruppen du aktivierst oder deaktivierst.
---
## 3. Abgrenzung zu ähnlichen Tools
### 3.1. Ruff vs. flake8 (+ Plugins)
**flake8** ist ein Linter; für viele Extras braucht man Plugins:
- z.B. `flake8-bugbear`, `flake8-import-order`, `pep8-naming` usw.
**Ruff:**
- Bietet die Funktionalität vieler flake8-Plugins „eingebaut“.
- Ist deutlich **schneller** (insbesondere bei großen Projekten).
- Wird oft als Drop-in-Ersatz für flake8 verwendet.
Aber:
- flake8 ist schon lange etabliert; manche Teams haben stark angepasste flake8-Setups, die man nicht 1:1 nach ruff übertragen kann.
- Einige Spezial-Plugins existieren ggf. nur für flake8.
---
### 3.2. Ruff vs. pylint
**pylint**:
- Sehr umfangreicher Linter (viele komplexe Regeln, u.a. über Projektstruktur, OOP-Patterns usw.)
- Langsam im Vergleich zu ruff
- Detaillierte Reports und Scores
**Ruff**:
- Fokus auf **Geschwindigkeit** und auf Regeln, die sich gut automatisieren/auto-fixen lassen.
- Viele „klassische“ Lint-Regeln, Naming, Imports, Security-Basics, aber nicht alle tiefgehenden Analysen von pylint.
- Für komplexe Architektur-Regeln wird weiterhin oft pylint oder andere Tools genutzt.
---
### 3.3. Ruff vs. black
**black**:
- Reiner **Formatter** macht nur Formatierung, keine Lint-Fehler (bis auf ganz wenige Ausnahmen).
- Sehr stabile, strikte Formatierung (Meinung: „The uncompromising code formatter“).
**Ruff**:
- Eigenständiger Formatter, der in vielen Projekten Black ersetzen kann.
- Zusätzlich: Linting, Import-Sortierung, Security-Regeln usw.
- Du kannst:
- nur ruff als Formatter nutzen, oder
- ruff als Linter + black als Formatter (dann `ruff format` nicht verwenden), wenn dein Team bereits stark auf black setzt.
---
### 3.4. Ruff vs. isort
**isort**:
- Spezialisiert auf das Sortieren von Imports.
**Ruff**:
- Hat eine integrierte Import-Sortierung (Regelgruppe `I`).
- Für die meisten Fälle reicht ruff völlig aus.
- Wenn ihr sehr spezielle Import-Sortierregeln braucht, ist isort manchmal noch flexibler, aber das wird immer weniger relevant.
---
### 3.5. Ruff vs. mypy/pyright (Typprüfung)
**mypy/pyright**:
- Statische Typprüfer: sie prüfen, ob die Typannotationen sinnvoll zusammenpassen.
- Finden z.B. Fehler wie: „Funktion gibt laut Typ `str` zurück, tatsächlich aber `int`“.
**Ruff**:
- Enthält Regeln, die mit Typannotationen arbeiten (z.B. Style, Safety), aber **kein vollwertiger Typprüfer**.
- Typfehler (im Sinne von mypy) sollten weiterhin mit mypy oder pyright geprüft werden.
---
### 3.6. Ruff vs. bandit (Security)
**bandit**:
- Spezialisiertes Security-Tool für Python.
**Ruff**:
- Hat viele bandit-Regeln integriert (Regelgruppe `S`).
- Deckt gängige Sicherheitsfallen ab (z.B. `eval` auf untrusted Input, hartkodierte Passwörter etc.).
- Für tiefgehende Security-Audits kann ein spezialisiertes Tool trotzdem sinnvoll sein.
---
## 4. Welche Probleme löst ruff?
### 4.1. Performance-Probleme in großen Projekten
Früher:
- flake8 + black + isort + bandit + mypy
→ viele Tools, mehrfaches Einlesen des Codes, CI dauert lange.
Mit ruff:
- Ein Tool übernimmt Linting, Formatierung, Importe, einen großen Teil der Security-Regeln.
- Deutlich weniger Laufzeit, besonders in CI-Pipelines oder bei großen Repositories.
---
### 4.2. Zu viele Tools, komplizierte Konfiguration
Problem:
- Unterschiedliche Konfigurationsdateien (`.flake8`, `pyproject.toml`, `setup.cfg`, `.isort.cfg`, `pyproject.toml` für black…)
- Mehr Aufwand beim Onboarding neuer Teammitglieder.
Ruff:
- Typischerweise alles in **einer** Konfiguration (`pyproject.toml`).
- Weniger bewegliche Teile, einfachere Wartung.
---
### 4.3. Inkonsequente Codequalität im Team
Ohne einheitliche Tools:
- Jede:r schreibt etwas anders.
- Diskussionen in Code-Reviews drehen sich um Stil statt Inhalte.
- Fehler (z.B. ungenutzte Variablen, potentielle Bugs) werden erst spät bemerkt.
Mit ruff:
- Gemeinsame, automatisierte Regeln.
- Automatische Fixes für vieles (z.B. im Editor oder Pre-Commit-Hooks).
- Code-Reviews können sich auf Architektur und Logik konzentrieren.
---
### 4.4. Technische Schulden reduzieren
In älteren Projekten:
- Viele kleine Stil- und Qualitätsprobleme haben sich angesammelt.
- Niemand möchte „alles mal eben aufräumen“, weil Tools zu langsam sind oder es zu viel ist.
Mit ruff:
- Durch die Geschwindigkeit kann man auch große Codebasen lintern.
- Schrittweise Verbesserung möglich: z.B. zunächst nur wichtige Regelgruppen aktivieren, später mehr.
---
## 5. Herausforderungen bei der Nutzung von ruff
### 5.1. Zu viele Meldungen am Anfang
Wenn du ruff das erste Mal auf ein älteres Projekt loslässt, bekommst du oft hunderte oder tausende Meldungen.
Strategie:
- Nur einen Teil der Regeln aktivieren (z.B. nur „kritische“ oder klar hilfreiche).
- Bestehende Verstöße einmalig ignorieren (per `--ignore` oder `--per-file-ignores`) und neue Verstöße blocken.
- Nach und nach alte Stellen aufräumen.
---
### 5.2. Regeln verstehen und anpassen
Ruff hat sehr viele Regeln. Nicht alle passen zu jedem Projekt.
- Manche Regeln sind sehr streng (z.B. bestimmte Naming- oder Docstring-Regeln).
- Du musst überlegen: Welche Regeln sind für unser Team sinnvoll?
Lösung:
- Regeln gezielt aktivieren/deaktivieren.
- Dokumentieren, warum bestimmte Regeln aktiv oder abgeschaltet sind.
---
### 5.3. Wechsel von bestehender Tool-Landschaft
Wenn ihr schon flake8, black, isort etc. nutzt:
- Müssen Einstellungen in ruff nachgebaut werden.
- Manche Teams werden black nicht sofort durch ruff format ersetzen wollen.
Ein pragmatischer Weg:
1. Zuerst ruff als **Linter** einführen (Formatierung bleibt bei black).
2. Wenn gewünscht, später ruff format testen und ggf. black ersetzen.
---
### 5.4. Auto-Fixes mit Vorsicht genießen
Ruff kann sehr viel automatisch reparieren:
- In der Regel gut, aber:
- Bei manchen Regeln sollte man prüfen, ob die Änderung wirklich die Absicht trifft.
- In kritischen Bereichen (z.B. Security-sensible Logik) ggf. Auto-Fixes nicht blind akzeptieren.
Empfehlung:
- Auto-Fixes lokal ausführen, dann diff anschauen.
- In CI eher nur prüfen, nicht fixen.
---
### 5.5. Editor-Integration
Ruff hat gute Unterstützung in vielen Editoren (VS Code, PyCharm, Neovim usw.), aber:
- Man muss oft ein Plugin oder eine Extension installieren.
- Manchmal überschneidet sich das mit vorhandenen Tools (z.B. Black-Extension vs. Ruff-Formatter); das muss sauber konfiguriert werden.
---
## 6. Praxisnahe Beispiele
### 6.1. Installation von ruff
Typisch über `pip`:
```bash
pip install ruff
```
Oder als dev-Abhängigkeit in `pyproject.toml` (Poetry/uv/pip-tools etc.).
---
### 6.2. Einfacher Aufruf
Linting:
```bash
ruff check .
```
Mit automatischen Fixes:
```bash
ruff check . --fix
```
Formatierung:
```bash
ruff format .
```
---
### 6.3. Minimale Konfiguration in `pyproject.toml`
```toml
[tool.ruff]
target-version = "py311" # welche Python-Version ihr nutzt
line-length = 88 # maximale Zeilenlänge
exclude = ["venv", ".venv", "build", "dist"]
[tool.ruff.lint]
select = ["E", "F", "I", "B", "UP"] # Regelgruppen: Errors, Flake, Imports, Bugbear, pyupgrade
ignore = ["E501"] # Beispiel: lange Zeilen ignoriere ich (wenn ich black nutze)
[tool.ruff.format]
# Beispiel: wenn ihr black-kompatible Einstellungen wollt
quote-style = "double"
indent-style = "space"
line-ending = "auto"
```
- `select` gibt an, welche Regelgruppen aktiv sind.
- `ignore` hebt einzelne Regelcodes auf (z.B. `E501` für Zeilenlänge).
---
### 6.4. Beispiel: Unbenutzte Variable und schlechtes `None`-Checking
Code:
```python
def process(items):
count = len(items)
unused = 0
if items == None:
print("No items")
return count
```
Ruff meldet u.a.:
- `F841` (unused variable `unused`)
- `E711` (Vergleich mit `None` mit `==` statt `is`)
Mit `ruff check . --fix` könnte daraus werden:
```python
def process(items):
count = len(items)
if items is None:
print("No items")
return count
```
---
### 6.5. Beispiel: Imports aufräumen
Code:
```python
import os
import sys
import json
import requests
def get_data(url):
r = requests.get(url)
return r.json()
```
Hier wird `os`, `sys` und `json` nicht genutzt.
Ruff meldet:
- `F401` (unused imports: os, sys, json)
Nach `ruff check . --fix`:
```python
import requests
def get_data(url):
r = requests.get(url)
return r.json()
```
---
### 6.6. Beispiel: Einsatz mit pre-commit
Viele Teams nutzen [pre-commit](https://pre-commit.com/), damit Checks automatisch vor jedem Git-Commit laufen.
`.pre-commit-config.yaml`:
```yaml
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.5 # Beispielversion, ggf. aktualisieren
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
```
Damit werden:
- Linting + Auto-Fix vor jedem Commit ausgeführt,
- Formatierung automatisch angewendet.
---
## 7. Zusammenfassung
- **Ruff** ist ein modernes, sehr schnelles Tool zur Verbesserung der Code-Qualität in Python.
- Es kombiniert:
- Linting (Fehler und Stil),
- Formatierung,
- Import-Sortierung,
- viele Sicherheits- und Modernisierungsregeln.
- Es ersetzt in vielen Projekten:
- flake8 (+ viele Plugins),
- isort,
- teilweise black,
- teilweise bandit.
- Es löst Probleme wie:
- lange Tool-Laufzeiten,
- fragmentierte Konfiguration,
- inkonsistente Codequalität.
- Herausforderungen sind v.a.:
- Auswahl und Anpassung der Regeln,
- Umstieg von bestehenden Tools,
- Umgang mit großen Mengen an Anfangs-Warnungen.
Wenn du möchtest, kann ich dir im nächsten Schritt eine **konkrete Beispielkonfiguration für ein kleines oder ein großes Projekt** vorschlagen (inkl. welche Regelgruppen sinnvoll sind und welche man am Anfang lieber auslässt).