TATECHATLAS
◎ Deutsch
Programmierung / Anleitung

Erstellung und Nutzung eines Wheelhouse für Offline-Python-Installationen

Ein Wheelhouse ist ein Verzeichnis mit vorinstallierten Wheels, das auf einer Maschine mit Netzwerkzugriff erstellt und auf einem isolierten Zielsystem installiert wird. Es nutzt pip wheel, tar-Archive und die Installation via --no-index --no-deps --force-reinstall.

Auf dieser Seite

Ein Wheelhouse ist ein Verzeichnis von vorab erstellten Wheel-Dateien, das Sie auf einer Maschine mit Netzwerkzugriff erstellen und anschließend auf eine isolierte Zielmaschine übertragen. Die Build-Maschine liest eine fixierte (pinned) Requirements-Datei, führt pip wheel mit --wheel-dir aus, um jede Abhängigkeit zu kompilieren, und paketiert das Verzeichnis mit tar. Auf der Zielmaschine entpacken Sie das Archiv und führen pip install mit --no-index --no-deps --force-reinstall aus, sodass pip niemals Kontakt zu PyPI aufnimmt und nur die beigefügten Wheels installiert. Eine Hash-Prüfung kann durch das Hinzufügen von --hash-Einträgen in der Requirements-Datei implementiert werden, was die Integrität der Pakete während des Build-Schritts verifiziert. Diese Methode ist angemessen, wenn das Zielsystem keinen Netzwerkzugriff hat, Sie eine Rekompilierung auf dem Zielsystem vermeiden wollen und Sie das Betriebssystem sowie die Architektur kontrollieren können. Es ist kein Ersatz für einen privaten Index, da das Archiv ein statischer Snapshot ist, typischerweise OS- und architekturspezifisch ist und keine dauerhafte Verfügbarkeit oder Zugriffskontrolle bietet.

Erstellung des Wheelhouse mit pip wheel

Der Kernworkflow beginnt mit einer fixierten Requirements-Datei. Führen Sie python -m pip wheel -r requirements.txt --wheel-dir=/tmp/wheelhouse aus, um jede Abhängigkeit in ein Wheel zu kompilieren und im Wheelhouse-Verzeichnis zu speichern. Die Build-Maschine übernimmt die Kompilierung, sodass die Zielmaschine keinen Compiler oder Build-Tools benötigt. Nach Abschluss des Befehls enthält das Wheelhouse-Verzeichnis für jedes Paket eine Wheel-Datei, einschließlich der transitiven Abhängigkeiten. Der nächste Schritt besteht darin, dieses Verzeichnis zu archivieren, damit es übertragen werden kann. Führen Sie auf einem modernen Unix-System tar -cjvf wheelhouse.tar.bz2 -C /tmp/wheelhouse . aus, um ein einzelnes komprimiertes Archiv zu erstellen. Dieses Archiv wird in die isolierte Umgebung übertragen. Die Requirements-Datei ist die Eingabe für diesen Schritt und muss daher vor dem Build exakt und vollständig sein.

mkdir -p /tmp/wheelhouse && python -m pip wheel -r requirements.txt --wheel-dir=/tmp/wheelhouse && tar -cjvf wheelhouse.tar.bz2 -C /tmp/wheelhouse .

Generieren Sie die Requirements-Datei mit pip freeze auf der Build-Maschine und überprüfen Sie anschließend, ob die fixierte Datei jede transitive Abhängigkeit enthält, bevor Sie pip wheel ausführen. Dies verhindert, dass fehlende Pakete zu einer fehlgeschlagenen Offline-Installation führen.

Installation aus dem Wheelhouse ohne Netzwerkzugriff

Entpacken Sie das Archiv auf der Zielmaschine in ein temporäres Verzeichnis und führen Sie dann pip install mit drei wichtigen Flags aus. --no-index weist pip an, keinen Paketindex zu kontaktieren, sodass es nicht auf PyPI zurückgreifen kann. --no-deps verhindert, dass pip Abhängigkeiten außerhalb des Bundles auflöst oder installiert, was sicher ist, da die Requirements-Datei bereits jedes Paket auflistet. --force-reinstall stellt sicher, dass die beigefügten Wheels installiert werden, selbst wenn bereits eine passende Version vorhanden ist. Der Befehl python -m pip install --force-reinstall --no-index --no-deps /tmp/wheelhouse/* installiert alle Wheels aus dem entpackten Verzeichnis. Diese Sequenz ermöglicht eine echte Offline-Installation, da während des Installationsschritts keine Netzwerkanfrage erfolgt. Die Requirements-Datei muss bereits jede transitive Abhängigkeit enthalten, da --no-deps sonst zu einer unvollständigen Umgebung führt.

tar -xvf wheelhouse.tar.bz2 -C /tmp/wheelhouse && python -m pip install --force-reinstall --no-index --no-deps /tmp/wheelhouse/*

Vorbereitung einer fixierten Requirements-Datei

Ein Wheelhouse wird aus einer Requirements-Datei mit exakten Versionsfixierungen erstellt. Sie können diese Datei mit pip freeze generieren, welche die in der aktuellen Umgebung installierten Pakete aufzeichnet, einschließlich transitiver Abhängigkeiten und nicht nur der Top-Level-Pakete. Jede Zeile verwendet den == Operator, um eine spezifische Version anzufordern, zum Beispiel SomePackage == 1.2.3. Die Fixierung schützt Sie vor Fehlern oder Inkompatibilitäten in neu veröffentlichten Versionen, da pip während der Build- oder Installationsschritte nichts aktualisieren wird. Die Requirements-Datei ist die Eingabe für den Schritt der Wheel-Erstellung und muss daher vor dem Ausführen von pip wheel vollständig und korrekt sein. Wenn in der Datei eine transitive Abhängigkeit fehlt, schlägt die Offline-Installation fehl, da --no-deps verhindert, dass pip diese von einem Index abruft. Überprüfen Sie die generierte Datei, um sicherzustellen, dass sie jede transitive Abhängigkeit enthält, bevor Sie pip wheel ausführen.

Archivierung des Wheelhouse für den Transfer

Sobald das Wheel-Verzeichnis gefüllt ist, konvertieren Sie es mit tar in ein einzelnes portables Archiv. Der Befehl tar -cjvf wheelhouse.tar.bz2 -C /tmp/wheelhouse . erstellt ein komprimiertes tar-Archiv, das alle Wheel-Dateien enthält. Dieses Archiv wird in die isolierte Umgebung übertragen. Das Archiv ist ein statischer Snapshot des Zustands der Build-Maschine und bewahrt so die exakt kompilierten Pakete und deren Versionen. Es enthält keine Build-Skripte oder Quellcode, sondern nur die installationsbereiten Wheels. Das Archiv muss auf die Zielmaschine übertragen werden, bevor die Installation beginnen kann. Da das Archiv eine einzelne Datei ist, lässt es sich leicht zwischen Maschinen bewegen, ist jedoch nicht portabel über verschiedene Betriebssysteme oder CPU-Architekturen hinweg.

Hinzufügen von Hash-Verifizierungen zum Wheelhouse-Workflow

Die Hash-Prüfung kann mit der Wheelhouse-Methode kombiniert werden, da beide eine Requirements-Datei verwenden. Sie fügen --hash-Einträge zur Requirements-Datei hinzu, zum Beispiel FooProject == 1.2 --hash=sha256:2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824. Diese Hashes werden verifiziert, wenn pip wheel Pakete herunterlädt, was vor einer Kompromittierung des Quell-Index oder der HTTPS-Zertifikatskette schützt. Es schützt auch davor, dass ein Paket geändert wird, ohne dass sich die Versionsnummer auf Indexen ändert, die dies zulassen. Dies ist eine Integritätsschicht über dem Offline-Bundle. Die Hashes müssen gültig sein und mit den Paketen im Archiv übereinstimmen. Wenn die Hashes nicht übereinstimmen, wird pip sich weigern, das Paket zu verwenden, was den Build vor stillschweigenden Änderungen schützt. Der Hash-Prüfmodus ist eine Integritätsschicht und keine arbeitssparende Alternative zu einem privaten Index-Server, da er nicht die Verfügbarkeitsvorteile eines privaten Index oder einer vendorierten Bibliothek bietet.

Deklaration von Build-Abhängigkeiten in pyproject.toml

Die [build-system] Tabelle in pyproject.toml deklariert Abhängigkeiten auf Python-Ebene, die installiert sein müssen, um das Build-System des Projekts auszuführen. Der Schlüssel requires listet diese Abhängigkeiten auf, zum Beispiel requires = [setuptools]. Diese Build-Zeit-Anforderungen beeinflussen, was pip wheel kompiliert, da das Build-Backend sie benötigt, um das Wheel zu erstellen. Das Verständnis dieser Tabelle hilft sicherzustellen, dass das Wheelhouse alle notwendigen Build-Tool-Abhängigkeiten erfasst, damit die Kompilierung auf der Build-Maschine erfolgreich ist. Wenn das Build-System zusätzliche Pakete benötigt, sollten diese in requires aufgeführt werden, damit die Build-Maschine sie vor dem Ausführen von pip wheel installieren kann. Die Standardsemantik gilt, wenn keine pyproject.toml-Datei vorhanden ist, aber eine explizite Tabelle macht die Build-Anforderungen klar und reproduzierbar.

Portabilitätsgrenzen und wann ein Wheelhouse nicht ausreicht

Ein Wheelhouse enthält kompilierte Pakete, die typischerweise OS- und architekturspezifisch sind, sodass Archive nicht zwangsläufig portabel über verschiedene Maschinen hinweg sind. Dasselbe Wheel wird ohne Rekompilierung nicht auf einem anderen Betriebssystem oder einer anderen CPU-Architektur funktionieren. Diese Methode erfordert zudem eine Build-Maschine mit Netzwerkzugriff; sie hilft nicht, wenn keine Maschine PyPI erreichen kann. Ein Wheelhouse ist kein Ersatz für einen privaten Index, wenn Sie plattformübergreifende Unterstützung oder einen lebendigen Audit-Trail über ein statisches Archiv hinaus benötigen. Die Hash-Prüfung allein bietet Integrität, aber keine Verfügbarkeit, und ein Wheelhouse bietet Verfügbarkeit nur für die exakten Pakete und Plattformen, die es enthält. Wenn Sie mehrere Plattformen unterstützen müssen, müssen Sie separate Wheelhouses für jede Zielumgebung erstellen. Das Archiv ist ein Snapshot, kein Dienst, und kann daher keine dauerhafte Verfügbarkeit oder Zugriffskontrolle bieten.

Wann ein Wheelhouse das richtige Werkzeug ist

Ein Wheelhouse ist das richtige Werkzeug, wenn die Zielumgebung keinen Netzwerkzugriff auf PyPI hat, Sie zeitintensive Rekompilierungen auf der Zielmaschine vermeiden wollen und Sie das Betriebssystem sowie die Architektur kontrollieren können. Es paketiert die gesamte Kompilierungsarbeit in einem einzigen Archiv, was sich deutlich vom bloßen Fixieren von Versionen oder der alleinigen Verwendung von Hash-Prüfungen unterscheidet. Die Fixierung schützt vor Fehlern in neuen Versionen und die Hash-Prüfung fügt Integrität hinzu, aber keine von beiden bietet die Verfügbarkeit oder den Komfort einer Offline-Installation eines Wheelhouse. Das Wheelhouse ist ein Bündel aus vorab erstellten Wheels, die die Zielmaschine installiert, ohne einen Index zu kontaktieren. Dieser Ansatz funktioniert über Betriebssysteme und Architekturen hinweg nur, wenn die Build- und Zielmaschinen dieselbe Plattform teilen. Es ist eine praktische Lösung für isolierte Deployments, bei denen der Netzwerkzugriff nicht verfügbar oder eingeschränkt ist.

Was Sie prüfen sollten

  • Die Requirements-Datei muss jedes Paket mit == fixieren und transitive Abhängigkeiten enthalten, nicht nur Top-Level-Pakete.
  • Die Build-Maschine muss Netzwerkzugriff haben, um alle Abhängigkeiten vor der Archivierung herunterzuladen und zu kompilieren.
  • Die Zielmaschine muss dasselbe Betriebssystem und dieselbe CPU-Architektur wie die Build-Maschine verwenden, damit die Wheels kompatibel sind.
  • Der Installationsbefehl muss --no-index, --no-deps und --force-reinstall enthalten, um Netzwerkzugriff und externe Abhängigkeitsauflösung zu verhindern.
  • Das Archiv muss vor dem Transfer mit tar aus dem Wheel-Verzeichnis erstellt und vor der Installation entpackt werden.
  • Hash-Prüfungs-Einträge in der Requirements-Datei müssen gültig sein und mit den Paketen im Archiv übereinstimmen.
  • Das Wheelhouse enthält kompilierte Pakete und ist nicht portabel über verschiedene Betriebssysteme oder Architekturen hinweg.
  • Ein Wheelhouse ersetzt keinen privaten Index für dauerhafte Verfügbarkeit, Zugriffskontrolle oder Audit-Management.

Ein Wheelhouse enthält kompilierte Pakete, die typischerweise OS- und architekturspezifisch sind, sodass Archive nicht unbedingt portabel zwischen Maschinen sind. Der Ansatz erfordert eine Build-Maschine mit Netzwerkzugriff; er hilft nicht, wenn keine Maschine PyPI erreichen kann. Kompilierte Wheels können plattformspezifischen Binärcode enthalten, sodass Cross-Kompilierung durch diese Methode allein nicht unterstützt wird. Das Archiv ist ein statischer Snapshot und bietet keine dauerhafte Verfügbarkeit oder ACL-Verwaltung wie ein privater Index-Server. Die Verwendung von --no-deps bedeutet, dass der Operator sicherstellen muss, dass die Requirements-Datei bereits jede transitive Abhängigkeit auflistet.

Quellen

  1. pip: repeatable installs ↗
  2. Python Packaging: pyproject.toml specification ↗
Nach oben ↑