Python-Skripte aus n8n aufrufen
Update (März 2026): Seit der Veröffentlichung dieses Artikels nutze ich Claude Code + n8n-MCP, um n8n-Workflows direkt vom Terminal aus zu erstellen und zu debuggen. Diese Kombination macht den FastAPI-Ansatz unten noch mächtiger: Claude Code erstellt das Workflow-Gerüst, n8n führt es aus, Python übernimmt die schwere Arbeit. Das komplette Setup habe ich hier beschrieben.
Manchmal muss man ein Python-Skript aus einem n8n-Workflow heraus aufrufen. Zwar bietet n8n einen Code-Node mit Python-Unterstützung, aber dessen Implementierung ist begrenzt. Will man die volle Power von Python nutzen – inklusive externer Bibliotheken, komplexer Berechnungen oder Machine Learning-Modelle – braucht man eine eigenständige Python-Umgebung.
TL;DR: Nutze FastAPI, um Python-Skripte als API-Endpunkte zu verpacken, containerisiere sie mit Docker und rufe sie aus n8n-Workflows per HTTP-Request auf. Das umgeht n8ns limitierten Python Code-Node und erschließt die volle Python-Power inklusive externer Bibliotheken.
In diesem Guide zeige ich dir, wie du ein Python-Skript in einen n8n-Workflow integrierst, indem du FastAPI für einen API-Endpunkt verwendest. Egal ob Bildverarbeitung, Datenmanipulation oder andere Custom-Tasks – dieser Ansatz bringt Pythons Macht in n8ns Automatisierungswelt.
Wir behandeln:
- Das Verpacken eines Python-Skripts in eine FastAPI-Anwendung.
- Die Containerisierung mit Docker.
- Den Aufruf aus einem n8n-Workflow.
Am Ende hast du ein funktionierendes Setup, bei dem n8n dein Python-Skript per HTTP-Request triggert.
Voraussetzungen
Bevor wir loslegen, stelle sicher, dass du folgendes hast:
- Docker installiert auf deiner Maschine oder deinem Server.
- n8n am Laufen (vorzugsweise in Docker, andere Setups funktionieren aber auch).
- Grundkenntnisse in Python, Docker und n8n-Workflows.
- Ein Glas Tiger Balm für den Mut-Boost.
Schritt 1: Dein Python-Skript erstellen
Beginnen wir mit einem einfachen Python-Skript. Für dieses Beispiel verwenden wir ein Bildgrößen-Änderungs-Skript, aber du kannst es gegen jede beliebige Python-Logik austauschen.
Beispiel-Skript: resize.py
Dieses Skript ändert die Größe eines Bildes auf ein 1000x1000-Quadrat, behält dabei das Seitenverhältnis bei und fügt einen weißen Hintergrund hinzu.
Ich habe dieses Beispiel gewählt, weil der Image-Resize-Node in n8n momentan nicht richtig funktioniert. n8n-Leute 😵💫, das müsst ihr reparieren!
from PIL import Image
import argparse
def resize_image(input_path, output_path, size=1000):
# Open the original image
original_image = Image.open(input_path)
width, height = original_image.size
# Calculate new dimensions while preserving aspect ratio
ratio = min(size / width, size / height)
new_width = int(width * ratio)
new_height = int(height * ratio)
# Resize the image
resized_image = original_image.resize((new_width, new_height), Image.LANCZOS)
# Create a white 1000x1000 background and paste the resized image
final_image = Image.new("RGB", (size, size), (255, 255, 255))
offset_x = (size - new_width) // 2
offset_y = (size - new_height) // 2
final_image.paste(resized_image, (offset_x, offset_y))
# Save the result
final_image.save(output_path)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Resize image to 1000x1000")
parser.add_argument("input_image", help="Path to input image")
parser.add_argument("output_image", help="Path to output image")
args = parser.parse_args()
resize_image(args.input_image, args.output_image)
Speichere das als resize.py. Es nimmt einen Input-Bildpfad und einen Output-Pfad als Argumente.
Schritt 2: Einen FastAPI-Wrapper erstellen
Anstatt nur eine FastAPI-Anwendung zu bauen, verpacken wir unser Python-Skript mit einer API und machen es für n8n zugänglich. Dieser Wrapper ermöglicht es n8n, über HTTP-Requests mit dem Skript zu interagieren und sorgt für bessere Flexibilität und Skalierbarkeit.
💡 Eine andere Option wäre Flask gewesen, ein beliebtes leichtgewichtiges Framework für APIs. Wir haben uns aber für FastAPI entschieden, weil es asynchrone Unterstützung, automatische Datenvalidierung und eingebaute OpenAPI-Dokumentation bietet – das macht es schneller und effizienter für API-Requests, besonders in Automatisierungsszenarien wie n8n.
Ein Hauptvorteil von FastAPI ist, wie einfach es sich erweitern lässt. Weitere Skripte hinzuzufügen ist so simpel wie neue Endpunkte zu definieren. Brauchst du zum Beispiel ein weiteres Skript für Graustufen-Filter, erstellst du einfach eine neue Route wie /grayscale und rufst das entsprechende Skript auf. Dieser modulare Ansatz macht es leicht, die API zu skalieren und mehrere Python-Skripte in deinen n8n-Workflow zu integrieren, ohne bestehende Endpunkte zu ändern.
## app.py
from fastapi import FastAPI, UploadFile, File
from fastapi.responses import StreamingResponse
import subprocess
import tempfile
import os
import io
app = FastAPI()
@app.post("/resize")
async def resize_image(file: UploadFile = File(...)):
# Create temporary files for input and output
with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as input_file:
input_path = input_file.name
input_file.write(await file.read())
with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as output_file:
output_path = output_file.name
# Run the resize script
try:
subprocess.run(["python", "resize.py", input_path, output_path], check=True)
except subprocess.CalledProcessError as e:
return {"error": f"Failed to resize image: {e}"}
# Read the resized image
with open(output_path, "rb") as f:
image_data = f.read()
# Clean up temporary files
os.remove(input_path)
os.remove(output_path)
# Return the image as a response
return StreamingResponse(io.BytesIO(image_data), media_type="image/jpeg")
So funktioniert's:
- Der /resize-Endpunkt akzeptiert eine hochgeladene Datei.
- Er speichert die Datei temporär, ruft resize.py per subprocess auf und gibt das verkleinerte Bild zurück.
- Temporäre Dateien werden nach der Verarbeitung gelöscht, um Unordnung zu vermeiden.
Speichere das als app.py im selben Verzeichnis wie resize.py.
Anmerkung: Reflexion zum FastAPI-Ansatz mit subprocess vs Python-Klasse 🥊
Jazys wies mich darauf hin: "Nun, für einen Entwickler sticht so eine Zeile ins Auge. Am besten wäre es, eine Python-Klasse zu erstellen und diese Klasse aufzurufen. Wenn du irgendwann neue APIs hinzufügen willst, musst du sowieso deine app.py ändern, also könntest du Python gleich komplett integrieren."
Er hat absolut recht aus puristischer Sicht: Eine Python-Klasse (wie ImageProcessor) zur Kapselung der Logik, direkt in die FastAPI-Anwendung integriert, verbessert Robustheit, Performance und Wartbarkeit, besonders für eine sich entwickelnde Anwendung mit neuen Routen. Für einen Entwickler, der eine saubere, modulare und gut dokumentierte Lösung sucht (mit automatischer Swagger-Dokumentation), ist dieser Ansatz ideal (z.B. Import einer Klasse in app.py mit wiederverwendbaren Methoden).
Allerdings bevorzuge ich als pragmatischer Bastler und Nicht-Entwickler meine subprocess-Lösung: Sie erlaubt mir, schnell unabhängige kleine Skripte aufzurufen, ohne mir Gedanken über Robustheit oder Skalierbarkeit zu machen, was meinen einfachen Bedürfnissen entspricht. Danke für die scharfe Einsicht, Jazys – deine Entwickler-Weisheit leuchtet durch! 😉
Schritt 3: Abhängigkeiten definieren
Erstelle eine requirements.txt-Datei, um die benötigten Python-Pakete aufzulisten (übrigens: Wenn du genauso faul bist wie ich, kannst du eine requirements.txt automatisch generieren, indem du folgenden Befehl in deinem Projektverzeichnis ausführst: pip freeze > requirements.txt)
## requirements.txt
fastapi
uvicorn
pillow
python-multipart
Speichere das als requirements.txt.
Schritt 4: Mit Docker containerisieren
Um nahtlose Integration mit n8n zu gewährleisten und Konsistenz über verschiedene Umgebungen hinweg zu erhalten, containerisieren wir unsere FastAPI-Anwendung mit Docker. Da n8n wahrscheinlich in einem Docker-Container läuft, verbinden wir unsere Python-API von Anfang an mit demselben Docker-Netzwerk.
Zusätzlich erkunden wir zwei Ansätze: ein eigenständiges Dockerfile oder die Nutzung von docker compose für komplexere Setups. In speziellen Fällen, wie der Verarbeitung vieler Dateien, besprechen wir auch die Verwendung eines geteilten Volumes.
Netzwerk-Setup
Sowohl n8n als auch unsere Python-API müssen im selben Docker-Netzwerk kommunizieren. Identifiziere zuerst das Netzwerk, das dein n8n-Container verwendet:
docker inspect <n8n_container_name> | grep Network
Ersetze <n8n_container_name> mit dem Namen deines n8n-Containers (z.B. n8n-akc0oo0ogc0gkog0g8ww). Suche nach der NetworkID oder dem Networks-Bereich, um den Netzwerknamen zu finden (z.B. coolify oder n8n_default). Wir nutzen dieses Netzwerk, damit die Container über ihre Container-Namen miteinander sprechen können.
Anmerkung: Wir hätten unsere Python-Skripte auch ins Internet exponieren können, indem wir einen öffentlichen Port mappen (z.B. -p 8000:8000) und es mit HTTPS und Authentifizierung absichern. In diesem Fall haben wir uns aber entschieden, sie VPS-intern zu belassen. Das vereinfacht das Setup und vermeidet Sicherheitskomplexitäten, die entstehen, wenn Services der Welt ausgesetzt werden, wie Firewall-Management, Zertifikate, Reverse Proxy oder potenzielle Angriffe.
Option 1: Eigenständiges Dockerfile verwenden
Das ist der einfachste Ansatz, ideal für ein Single-Service-Setup.
Erstelle ein Dockerfile in deinem Projektverzeichnis:
FROM python:3.9
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY app.py .
COPY resize.py .
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
Baue das Docker-Image:
docker build -t fastapi-python-app .
Container ausführen
Führe den Container aus und verbinde ihn mit dem n8n-Netzwerk (ersetze <n8n_network> mit dem tatsächlichen Netzwerknamen):
docker run -d --name python-api --network <n8n_network> fastapi-python-app
--name python-api: Benennt den Container für einfache Referenzierung.--network <n8n_network>: Verbindet ihn mit n8ns Netzwerk, ermöglicht Kommunikation über http://python-api:8000.
Die API ist im Netzwerk unter http://python-api:8000/resize erreichbar.
Spezialfall: Geteiltes Volume
Wenn dein Workflow viele Dateien verarbeitet (z.B. Hunderte von Bildern verkleinern), möchtest du vielleicht vermeiden, Dateien wiederholt über HTTP zu übertragen. Stattdessen kannst du ein geteiltes Docker-Volume verwenden, um Dateien zu speichern, die sowohl für n8n als auch für die Python-API zugänglich sind. Zum Beispiel:
docker run -d --name python-api --network <n8n_network> -v /path/to/shared/folder:/data fastapi-python-app
-v /path/to/shared/folder:/data: Mountet ein Verzeichnis vom Host (/path/to/shared/folder) nach /data im Container.- Aktualisiere app.py, um Dateien von /data zu lesen/schreiben statt temporäre Dateien zu verwenden, und stelle sicher, dass n8n in dasselbe Volume schreiben kann. Das ist eher die Ausnahme als die Regel, da es die Container stärker koppelt, aber es ist effizient für Bulk-Dateioperationen.
Option 2: Docker Compose verwenden
Für ein strukturierteres Setup, besonders wenn du mehrere Services verwaltest oder das Netzwerk explizit definieren willst, nutze docker-compose.
Erstelle eine docker-compose.yml-Datei:
services:
python-api:
build: .
image: fastapi-python-app
container_name: python-api
command: uvicorn app:app --host 0.0.0.0 --port 8000
networks:
- n8n_network
networks:
n8n_network:
name: <n8n_network>
external: true
build: .: Baut das Image aus dem Dockerfile im aktuellen Verzeichnis.networks: Verbindet den Service mit dem bestehenden n8n-Netzwerk (ersetze <n8n_network> mit dem tatsächlichen Namen ausdocker network ls).
Bauen und Ausführen
Starte den Service:
docker compose up -d
Das startet den python-api-Container im angegebenen Netzwerk.
Geteiltes Volume mit Docker Compose
Für Szenarien mit vielen Dateien, füge ein Volume zur docker-compose.yml hinzu:
services:
python-api:
build: .
image: fastapi-python-app
container_name: python-api
command: uvicorn app:app --host 0.0.0.0 --port 8000
volumes:
- shared-data:/data
networks:
- n8n_network
volumes:
shared-data:
networks:
n8n_network:
name: <n8n_network>
external: true
volumes: Definiert ein benanntes Volume (shared-data), das bei /data im Container gemountet wird.- Falls n8n auch von dieser docker-compose.yml verwaltet wird, füge es als Service hinzu und verbinde es mit demselben Volume und Netzwerk. Andernfalls stelle sicher, dass n8ns Container dasselbe Volume separat mountet.
Verwaltung mit Docker Compose
Stoppen oder neustarten mit:
docker compose down
docker compose up -d
Schritt 5: Container verifizieren und testen
Bevor wir die Python-API mit n8n integrieren, bestätigen wir, dass der Container korrekt läuft und die API wie erwartet antwortet. Wir testen sie mit curl auf eine Weise, die du später direkt in n8ns HTTP Request-Node kopieren kannst für einen nahtlosen Übergang.
Container-Status prüfen
Bestätige, dass der Container läuft:
docker ps
Suche nach python-api in der Liste mit Status Up und ohne exponierte Ports (da wir ein internes Netzwerk verwenden). Falls er nicht läuft, prüfe die Logs:
docker logs python-api
Behebe Fehler (z.B. fehlende Dateien, Abhängigkeitsprobleme), indem du das Image bei Bedarf neu baust:
docker build -t fastapi-python-app .
docker run -d --name python-api --network <n8n_network> fastapi-python-app
API lokal testen
Teste den Endpunkt aus dem Docker-Netzwerk heraus mit curl:
docker run --rm --network <n8n_network> curlimages/curl curl -X POST -F "file=@/path/to/test.jpg" http://python-api:8000/resize -o output.jpg
- Ersetze /path/to/test.jpg mit einem Test-Bildpfad, mounte es bei Bedarf (z.B.
-v /local/path:/dataund verwendefile=@/data/test.jpg). - Verifiziere, dass output.jpg das verkleinerte Bild enthält.
Bonus: n8n-kompatibles curl-Kommando
Hier ist ein curl-Kommando, das du direkt auf deinem Host ausführen kannst (falls der Port exponiert ist) oder für n8n anpassen:
curl -X POST -F "file=@/path/to/test.jpg" http://python-api:8000/resize -o output.jpg
- Warum es nützlich ist: Dieses exakte Kommando kann in n8ns HTTP Request-Node über die Import-cURL-Option kopiert und in das "Raw Request"-Feld eingefügt werden (nach Anpassung des Dateipfads an n8ns Binärdaten). Es ist ein schneller Weg, den Request zu prototypen, bevor man in n8n feintuned.
- Falls du den Port lokal exponiert hast (z.B. mit
-p 8000:8000), führe das von deinem VPS aus, um außerhalb von Docker zu testen.
Wenn das funktioniert, ist die API bereit für n8n 😀.
Schritt 6: n8n für API-Aufrufe konfigurieren
In deiner n8n-Instanz:
- Öffne den Workflow-Editor.
- Füge einen HTTP Request-Node hinzu.
- Konfiguriere ihn so:

- URL: http://python-api:8000/resize (mit dem Container-Namen als Hostname).
- Method: POST.
- Send Binary Data: Diese Option aktivieren.
- Binary Property: Auf data setzen (oder den Namen deines binären Input-Feldes).
Bilddatei hinzufügen
Falls du ein Bild von der Festplatte verkleinerst:
- Füge einen Read Binary File-Node vor dem HTTP Request-Node hinzu.
- Setze den Dateipfad auf dein Input-Bild.
- Verbinde ihn mit dem HTTP Request-Node und stelle sicher, dass die Binärdaten durchfließen.

Falls dieser Content nützlich ist, helfen deine Klatscher 👏, Highlights 🖍️ oder Kommentare 💬 uns, relevanteres Material zu produzieren.
Schritt 7: Workflow testen
- Führe den n8n-Workflow aus.
- Prüfe die Ausgabe des HTTP Request-Nodes: Du solltest das verkleinerte Bild als Binärdaten zurückbekommen.
- Bewundere dieses Meisterwerk! 😆🔥
Fehlerbehebung
- "Connection refused": Stelle sicher, dass beide Container im selben Docker-Netzwerk sind und die URL mit dem Container-Namen übereinstimmt (python-api).
- "Module not found": Überprüfe requirements.txt doppelt und baue das Docker-Image neu.
- Dateiprobleme: Falls n8n die Input-Datei nicht findet, verifiziere, dass der Pfad innerhalb seines Containers zugänglich ist.
Jetzt bist du startklar!
Du kannst jetzt sicher Python-Skripte aus n8n aufrufen, ohne Nebenwirkungen auf deine Automatisierungsumgebung. Außerdem könntest du diese Skripte sogar außerhalb von n8n verwenden – aber das ist eine ganz andere Geschichte!
Frohes Automatisieren! Lass mich in den Kommentaren wissen, falls du auf Probleme stößt oder Fragen hast. 🚀
Ich habe die CLI-Struktur, Produktions-CLAUDE.md und Agent-Constraints, die ich in all meinen Automatisierungsprojekten verwende, in einem kostenlosen Kit dokumentiert. 3 Dateien, 10 Minuten.
Wie man Python-Skripte nahtlos in n8n-Workflows integriert: Ein praxisnaher Ansatz für Entwickler, die mehr aus ihrer Automatisierung herausholen wollen.