Ich weiß nicht, ob das in Ordnung ist, aber ich möchte die für das Paket benötigten Daten von etwas anderem als dem PyPI-Server abrufen und installieren.
Datendateibezogene Argumente, die in setup.py
, package_data und data_files beschrieben werden können, werden beide mit dem Quellcode verteilt.
Es scheint, dass nur Dateien unterstützt werden.
Daher habe ich den Befehl install_data, der während der Pip-Installation aufgerufen wurde, eingehakt, um die erforderlichen Dateien separat herunterzuladen.
Verwenden Sie zum Verknüpfen oder Ersetzen des Befehls das Schlüsselwortargument cmdclass in der Funktion setuptools.setup
.
Dies kann durch Übergeben eines Wörterbuchs mit der Implementierung als Wert erfolgen, wobei der zu ersetzende Befehlsname als Schlüssel verwendet wird. (Referenz: Integration neuer Befehle)
Die ursprüngliche Quelle des Befehls install_data, der dieses Mal ersetzt werden soll, ist hier. Ich habe einen benutzerdefinierten Befehl install_data als Referenz erstellt.
import distutils.command.install_data
from os import path
import site
import sys
import urllib
class CustomInstallData(distutils.command.install_data.install_data):
def run(self):
# self.data_Die Setup-Funktionsdaten in Dateien_Enthält den an das Argument files übergebenen Wert.
#das ist,(Liste der Speicherziele für Datendateien und Pfade für Datendateien)Da es für die Liste der Tapples verantwortlich ist, wird es einzeln verarbeitet.
for f in self.data_files:
if not isinstance(f, tuple):
continue
for i, u in enumerate(f[1]):
#Wenn der Datendateipfad keine URL ist, wird nichts unternommen.
if not u.startswith("http"):
continue
#Wenn die Zieldatendatei bereits lokal ist, verwenden Sie sie erneut.
base = path.basename(u)
f[1][i] = path.join(sys.prefix, f[0], base)
if not path.exists(f[1][i]):
f[1][i] = path.join(sys.prefix, "local", f[0], base)
if not path.exists(f[1][i]):
f[1][i] = path.join(site.getuserbase(), f[0], base)
if not path.exists(f[1][i]):
#Wenn nicht lokal gefunden, herunterladen.
f[1][i] = urllib.urlretrieve(u, base)[0]
#Die andere Verarbeitung wird auf den ursprünglichen Befehl übertragen.
return distutils.command.install_data.install_data.run(self)
Da die grundlegende Verarbeitung mit dem ursprünglichen Befehl install_data identisch ist,
Erstellen Sie eine Klasse, die distutils.command.install_data.install_data
erbt.
Beachten Sie, dass die übergeordnete Klasse "distutils.command.install_data.install_data" anstelle von "distutils.command.install_data" lautet.
Überschreiben Sie diese Methode, da die Ausführungsmethode der Hauptteil des Befehls ist.
self.data_files
enthält eine Liste von (Verzeichnis, Dateien)
Paaren, die an das Argument data_files der Setup-Funktion übergeben wurden # Installation von zusätzlichen Dateien).
Verzeichnis ist das Speicherziel für Datendateien, und Dateien ist eine Liste der zu installierenden Datendateipfade.
Extrahieren Sie einzelne Elemente aus "self.data_files" und extrahieren Sie einzelne Datendateipfade zur Verarbeitung daraus. Wenn der Datendateipfad keine URL ist, ist die normale Verarbeitung ausreichend, sodass nichts für sie getan wird.
Wenn die Zieldatendatei bereits installiert ist, möchte ich sie als Nächstes wiederverwenden, um unnötige Downloads zu vermeiden. Gemäß dem Handbuch wird die Datendatei in gespeichert.
Wenn das Verzeichnis ein relativer Pfad ist, wird es als relativer Pfad aus dem Installationspräfix interpretiert (sys.prefix für reine Python-Pakete, sys.exec_prefix für Pakete mit Erweiterungen).
Wenn der Dateiname, den Sie installieren möchten, "Dateiname" ist,
os.path.join(sys.prefix, directory, filename)
os.path.join(sys.exec_prefix, directory, filename)
Du kannst nachschauen. In meinem Ubuntu wurde es jedoch an der Stelle gespeichert, an der ich einen Schritt als "os.path.join (sys.prefix," local ", Verzeichnis, Dateiname)" anstelle eines der oben genannten Schritte ausgegraben habe. Daher wird im obigen Code auch der Pfad mit local überprüft.
Es ist auch möglich, dass das Paket mit pip install --user
im Benutzerverzeichnis installiert wird.
In diesem Fall wird das Paket unter site.USER_BASE
gespeichert
Im obigen Code wird "site.getuserbase ()" verwendet, um den Wert von "site.USER_BASE" abzurufen, und das Vorhandensein dieser Datei wird ebenfalls überprüft.
Wenn die Zieldatendatei nicht lokal gefunden wird, wird sie schließlich mit "urllib.urlretrieve" erfasst.
Der Rest der Verarbeitung entspricht dem ursprünglichen Befehl install_data, daher wird die Methode der übergeordneten Klasse aufgerufen.
Da distutils.command.install_data.install_data
eine alte Klasse ist, wird die Methode der übergeordneten Klasse von distutils.command.install_data.install_data.run (self)
aufgerufen.
Der Aufruf der Setup-Funktion mit dem obigen benutzerdefinierten Befehl lautet wie folgt (nicht verwandte Elemente werden weggelassen).
setup(
data_files=[(
"rgmining/data",
["http://times.cs.uiuc.edu/~wang296/Data/LARA/TripAdvisor/TripAdvisorJson.tar.bz2"]
)],
cmdclass={
"install_data": CustomInstallData
},
... #Andere Elemente weggelassen
)
CustomInstallData wird als Implementierungsklasse des Befehls install_data im Argument cmdclass übergeben. Jetzt können Sie die URL an data_files übergeben.
Um zu vermeiden, dass eine große Datei auf dem PyPI-Server registriert wird, haben wir die Methode zum Herunterladen der erforderlichen Datei von einem anderen Server zum Zeitpunkt der Pip-Installation zusammengefasst. Es ist jedoch nicht sehr gut für die Sicherheit, da es den Hash der erfassten Datei nicht überprüft. Erstens habe ich das Gefühl, dass es eine andere Methode gibt, ohne so etwas zu tun. Lassen Sie es mich bitte wissen, wenn Sie es wissen.
Recommended Posts