J'ai créé un serveur de "packages" PyPI personnel sur une boîte Debian 9 / Nginx pour que je puisse rendre les constructions de mon serveur déterministes. J'épingle tous mes packages Python et je dois m'assurer que les versions exactes de mes packages Python ainsi que leurs sous-dépendances sont toujours disponibles chaque fois que j'ai besoin de reconstruire mes serveurs de commerce électronique.
J'ai rempli ce serveur avec mes packages requis à l'aide du package pip2pi . Mais lorsque j'exécute la commande "pip install" sur un serveur client pour installer mes packages, j'obtiens l'erreur suivante:
Created temporary directory: /tmp/pip-ephem-wheel-cache-g_hx5tb1
Created temporary directory: /tmp/pip-req-tracker-1bt5psaw
Created requirements tracker '/tmp/pip-req-tracker-1bt5psaw'
Created temporary directory: /tmp/pip-install-dqvtv6ek
Looking in indexes: https://packages.example.com/simple/
Collecting django-rq
1 location(s) to search for versions of django-rq:
* https://packages.example.com/simple/django-rq/
Getting page https://packages.example.com/simple/django-rq/
Looking up "https://packages.example.com/simple/django-rq/" in the cache
Request header has "max_age" as 0, cache bypassed
Starting new HTTPS connection (1): packages.example.com:443
https://packages.example.com:443 "GET /simple/django-rq/ HTTP/1.1" 304 0
Analyzing links from page https://packages.example.com/simple/django-rq/
Skipping link https://packages.example.com/simple/django-rq/django-rq-0.9.0-py2.py3-none-any.whl (from https://packages.example.com/simple/django-rq/); wrong project name (not django-rq)
Cleaning up...
Removed build tracker '/tmp/pip-req-tracker-1bt5psaw'
Exception information:
Traceback (most recent call last):
File "/home/flaugher/pip3/venv/lib/python3.5/site-packages/pip/_internal/cli/base_command.py", line 179, in main
status = self.run(options, args)
File "/home/flaugher/pip3/venv/lib/python3.5/site-packages/pip/_internal/commands/install.py", line 315, in run
resolver.resolve(requirement_set)
File "/home/flaugher/pip3/venv/lib/python3.5/site-packages/pip/_internal/resolve.py", line 131, in resolve
self._resolve_one(requirement_set, req)
File "/home/flaugher/pip3/venv/lib/python3.5/site-packages/pip/_internal/resolve.py", line 294, in _resolve_one
abstract_dist = self._get_abstract_dist_for(req_to_install)
File "/home/flaugher/pip3/venv/lib/python3.5/site-packages/pip/_internal/resolve.py", line 242, in _get_abstract_dist_for
self.require_hashes
File "/home/flaugher/pip3/venv/lib/python3.5/site-packages/pip/_internal/operations/prepare.py", line 269, in prepare_linked_requirement
req.populate_link(finder, upgrade_allowed, require_hashes)
File "/home/flaugher/pip3/venv/lib/python3.5/site-packages/pip/_internal/req/req_install.py", line 196, in populate_link
self.link = finder.find_requirement(self, upgrade)
File "/home/flaugher/pip3/venv/lib/python3.5/site-packages/pip/_internal/index.py", line 688, in find_requirement
'No matching distribution found for %s' % req
pip._internal.exceptions.DistributionNotFound: No matching distribution found for django-rq
J'ai environ 40 packages dans mes besoins fichier, ce n'est donc qu'un exemple de ce qui se passe. Le package Django sera installé mais pip échouera avec le package django-extensions.
Si j'exécute cette commande sur l'un de mes serveurs clients, j'obtiens l'erreur ci-dessus:
pip install --verbose --index-url=https://packages.example.com/simple/ django-rq
Le fichier d'exigences ressemble à ceci:
directory: simple/django-redis-cache file: django-redis-cache-1.6.5.tar.gz
Maintenant, sur mon serveur de packages, le répertoire racine du package, / var / www / packages, contient les éléments suivants structure:
directory: simple/django-rq file: django_rq-0.9.0-py2.py3-none-any.whl
Cette structure de répertoire a été construite et les packages installés à l'aide de la commande pip2tgz de pip2pi:
pip install --index-url=https://packages.example.com/simple/ django-extensions Looking in indexes: https://packages.example.com/simple/ Collecting django-extensions Could not find a version that satisfies the requirement django-extensions (from versions: ) No matching distribution found for django-extensions
Voici les exigences fichier d'entrée lu par pip2tgz:
server {
...
root /var/www/packages;
...
}
Voici comment le répertoire racine nginx est défini sur le serveur de packages:
-i https://pypi.org/simple django==1.8.4 django-extensions=1.5.7 (more packages)
Le pare-feu de mon serveur de paquets est configuré pour autoriser les pings, me permettre d'accéder à SSH et à toutes les connexions http et https.
J'utilise Python 3.5.3 et pip 19.0.3 sur mes serveurs clients .
Je ne suis pas sûr de ce que je fais de mal. La commande pip semble correcte mais je me demande si le package pip2pi configure correctement mes répertoires de packages. Si je modifie l'argument d'index dans le fichier d'exigences de mon client par défaut, https://pypi.org/simple , tous les packages sont restaurés sans erreur.
MISE À JOUR 1
Si j'essaie d'installer django-extensions à partir de la ligne de commande au lieu de via un fichier d'exigences, je toujours une erreur:
pip2tgz /var/www/packages/ -r requirements.txt
En examinant mes autres paquets, je vois un modèle ici. L'erreur se produit chaque fois que j'essaie d'installer un package dans lequel le nom du fichier wheel contient un trait de soulignement ("_") mais le nom normalisé du répertoire du package contient un hypen ("-") par Python PEP 503.
Par exemple, django-rq échoue:
# /var/www/packages: âââ Django-1.8.4-py2.py3-none-any.whl âââ django_extensions-1.5.7-py2.py3-none-any.whl âââ simple   âââ django   â  âââ Django-1.8.4-py2.py3-none-any.whl -> ../../Django-1.8.4-py2.py3-none-any.whl   â  âââ index.html   âââ django-extensions   â  âââ django-extensions-1.5.7-py2.py3-none-any.whl -> ../../django_extensions-1.5.7-py2.py3-none-any.whl   â  âââ index.html   âââ index.html
D'un autre côté, django-redis-cache n'échoue pas:
-i https://packages.example.com/simple Django==1.8.4 django-extensions==1.5.7 (more packages)
Voici l'erreur:
pip install -r requirements.txt
La clé semble être la ligne 15 où il est dit "Ignorer le lien ... nom de projet incorrect ( pas django-rq). " Je ne sais pas pourquoi il ignore le lien.
3 Réponses :
Pour mon serveur de paquets privé, la seule chose qui fonctionnait était --extra-index-url:
--extra-index-url https://foo.redacted.com/ Django my_other_package
Cela vérifiera d'abord pypi, puis votre serveur privé. Une chose qui a aidé à le déboguer est d'utiliser --verbose pour montrer ce qui se passe avec la connexion.
L'ajout de l'argument détaillé est utile pour le débogage. Mais utiliser '--extra-index-url' au lieu de '--index-url' va à l'encontre de mon objectif car cela entraîne l'installation de la dernière version du paquet plutôt que de ma (ancienne) version épinglée.
Idée stupide; pourquoi ne pas simplement définir le numéro de version de votre package personnalisé sur quelque chose qui n'existe pas dans le référentiel normal? Ensuite, vous pouvez simplement utiliser --extra-index-url car cette version ne sera pas trouvée dans le référentiel pypi normal
Il semble que le projet pip2pi que vous utilisez est bogué et n'a pas été maintenu récemment, avec plusieurs problèmes ouverts concernant les points / tirets dans les noms de distribution:
Problème avec les packages avec tiret dans le nom # 84
Modification de dir2pi pour utiliser le nom de fichier d'origine dans le lien de fichier. # 85
Je recommande plutôt de consulter devpi-server . p>
Je travaille maintenant sur le didacticiel, mais il semblerait que le devpi crée un miroir de tout l'index PyPI, ce qui n'est pas ce que je veux. Cela me permettra-t-il de créer un index privé compatible PyPI sur mon serveur de packaging qui ne contient que la quarantaine de packages spécifiques dont j'ai besoin dans les versions dont j'ai besoin? Idéalement, j'ai besoin d'un outil qui prendra un fichier requirements.txt contenant une liste de packages épinglés, et n'installe que ces packages (de préférence leurs roues) sur mon serveur de packaging. Je ne veux pas refléter tout PyPI et ensuite installer les dernières versions de mes packages.
La mise en miroir de PyPI est une option de configuration pour devpi-server . Vous pouvez désactiver cela si vous ne le souhaitez pas.
Bien que très élégant et bien documenté, devpi ne semble pas être une bonne solution pour mes besoins. devppi semble davantage orienté vers une équipe de développement développant des packages Python. Je suis développeur solo avec une application web Python / Django. Je n'ai pas de fichier setup.py et je n'utilise pas tox. J'ai un fichier d'exigences que je transmets à virtualenv ou pipenv pour créer mon environnement virtuel. J'ai juste besoin d'un index PyPI privé où je peux télécharger des versions spécifiques de mes packages Python requis et rien de plus. Mais j'apprécie la suggestion.
Jim, pourquoi ne pas utiliser simplement un répertoire local, alors? Ou un partage réseau monté? Pip prend également en charge les chemins locaux pour «l'url d'index».
Il semble que pypi-server répondra le mieux à mes besoins. Il réussit à installer les packages sur lesquels pip2pi a échoué comme je l'ai décrit ci-dessus. Ce n'est pas trop compliqué à configurer et il peut être exécuté sur un serveur distant via Nginx ou Apache. J'ai trouvé cet article Configurer un serveur PyPI très utile (bien qu'il y ait eu quelques fautes de frappe).
Qu'est-ce que vous obtenez lorsque vous ouvrez
https://packages.example.com/simpledans votre navigateur?Comme vous vous en doutez, j'obtiens une liste de liens vers les fichiers wheel pour tous les packages installés sur le serveur de packages.
alors tout me va bien. essayez de spécifier l'option --extra-index-url pour installer pip à la ligne de commande
J'ai essayé mais j'obtiens toujours une erreur. Voir MISE À JOUR à la fin de ma question ci-dessus. Merci pour la suggestion.
On dirait que
pip2pienvoie un nom de projet incorrect si les tirets sont remplacés par des traits de soulignement dans le nom du package. Je ne sais pas si renommer les roues (par exempledjango_extensionsendjango-extensions) aidera, mais je conseillerais également de passer depip2pi code > àdevpi(voir la réponse de @ wim) si le serveur a des difficultés avec la substitution de nom de paquet.