Je ne sais pas si c'est correct de le faire, mais je veux obtenir les données nécessaires pour le paquet à partir d'autre chose que le serveur PyPI et l'installer.
Les arguments liés aux fichiers de données qui peuvent être décrits dans setup.py
, package_data et data_files, sont tous deux distribués avec le code source.
Il semble que seuls les fichiers soient pris en charge.
Par conséquent, j'ai accroché la commande install_data appelée pendant pip install
pour télécharger les fichiers nécessaires séparément.
Pour raccorder ou remplacer la commande, utilisez le mot-clé argument cmdclass dans la fonction setuptools.setup
.
Cela peut être fait en passant un dictionnaire avec l'implémentation comme valeur, en utilisant le nom de commande à remplacer comme clé. (Référence: Intégration de nouvelles commandes)
La source d'origine de la commande install_data à remplacer cette fois est ici. J'ai créé une commande install_data personnalisée pour référence.
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_Les données de la fonction de configuration dans les fichiers_Contient la valeur passée à l'argument files.
#c'est,(Liste des destinations de sauvegarde des fichiers de données et des chemins des fichiers de données)Puisqu'il est responsable de la liste des tapples, il est traité individuellement.
for f in self.data_files:
if not isinstance(f, tuple):
continue
for i, u in enumerate(f[1]):
#Si le chemin du fichier de données n'est pas une URL, rien n'est fait.
if not u.startswith("http"):
continue
#Si le fichier de données cible est déjà local, réutilisez-le.
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]):
#S'il n'est pas trouvé localement, téléchargez.
f[1][i] = urllib.urlretrieve(u, base)[0]
#Les autres traitements sont transférés vers la commande d'origine.
return distutils.command.install_data.install_data.run(self)
Le traitement de base étant le même que la commande d'origine install_data,
Créez une classe qui hérite de distutils.command.install_data.install_data
.
Notez que la classe parente est distutils.command.install_data.install_data
au lieu de distutils.command.install_data
.
Étant donné que la méthode d'exécution est le corps de la commande, remplacez cette méthode.
self.data_files
contient une liste de paires (directory, files)
passées à l'argument data_files de la fonction setup # installation-fichiers-supplémentaires).
directory est la destination de sauvegarde des fichiers de données et files est une liste de chemins de fichiers de données à installer.
Extrayez des éléments individuels de self.data_files
et extrayez-en les chemins de fichiers de données individuels pour le traitement.
Si le chemin du fichier de données n'est pas une URL, le traitement normal est suffisant, donc rien n'est fait pour eux.
Ensuite, si le fichier de données cible est déjà installé, je voudrais le réutiliser pour éviter les téléchargements inutiles. Selon le Manual, le fichier de données est enregistré dans.
Si le répertoire est un chemin relatif, il est interprété comme un chemin relatif à partir du préfixe d'installation (sys.prefix pour les packages Python purs, sys.exec_prefix pour les packages avec extensions).
Donc, si le nom du fichier que vous essayez d'installer est filename
,
os.path.join(sys.prefix, directory, filename)
os.path.join(sys.exec_prefix, directory, filename)
Tu peux vérifier. Cependant, dans mon Ubuntu, il a été enregistré en une seule étape en creusant ʻos.path.join (sys.prefix, "local", directory, filename) ʻ dans l'un des éléments ci-dessus. Par conséquent, dans le code ci-dessus, le chemin avec local est également vérifié.
Il est également possible que le paquet soit installé dans le répertoire utilisateur avec pip install --user
.
Dans ce cas, le package est enregistré sous site.USER_BASE
, donc
Dans le code ci-dessus, site.getuserbase ()
est utilisé pour obtenir la valeur de site.USER_BASE
, et l'existence de ce fichier est également vérifiée.
Enfin, si le fichier de données cible n'est pas trouvé localement, il est obtenu en utilisant ʻurllib.urlretrieve`.
Le reste du traitement est identique à la commande install_data d'origine, la méthode de la classe parente est donc appelée.
Puisque distutils.command.install_data.install_data
est une ancienne classe, la méthode de la classe parente est appelée par distutils.command.install_data.install_data.run (self)
.
L'appel de la fonction de configuration à l'aide de la commande personnalisée ci-dessus est le suivant (les éléments non liés sont omis).
setup(
data_files=[(
"rgmining/data",
["http://times.cs.uiuc.edu/~wang296/Data/LARA/TripAdvisor/TripAdvisorJson.tar.bz2"]
)],
cmdclass={
"install_data": CustomInstallData
},
... #Autres éléments omis
)
CustomInstallData est passé en tant que classe d'implémentation de la commande install_data dans l'argument cmdclass. Vous pouvez maintenant transmettre l'URL à data_files.
Afin d'éviter d'enregistrer un fichier énorme sur le serveur PyPI, nous avons résumé la méthode de téléchargement du fichier nécessaire à partir d'un autre serveur au moment de l'installation de pip. Cependant, ce n'est pas très bon pour la sécurité car il ne vérifie pas le hachage du fichier acquis. En premier lieu, je pense qu'il existe une autre méthode sans faire une chose aussi gênante, alors faites-le moi savoir si vous la connaissez.
Recommended Posts