[PYTHON] L'histoire de l'erreur de hachage est apparue lors de l'utilisation de Pipenv

Qu'est-ce que c'est

Un jour, alors que j'utilisais Pipenv, j'ai eu une erreur mystérieuse.

J'ai eu du mal à comprendre la cause, alors j'ai décidé de l'écrire sous forme de mémo. Finalement, il a été résolu, donc si vous souffrez de symptômes similaires et que vous voulez juste savoir comment y faire face, veuillez aller à Solution.

Un jour, alors que j'utilisais Pipenv, j'ai remarqué une erreur mystérieuse

La première fois que j'ai remarqué cette erreur, c'était lorsque je voulais mettre en place un test automatisé dans CI. J'écrivais du code pour exécuter un test automatisé dans un environnement docker, mais j'ai remarqué l'erreur suivante lors de l'exécution de pipenv sync ou pipenv install dans docker.

An error occurred while installing readme-renderer==24.0 --hash=sha256:bb16f55b259f27f75f640acf5e00cf897845a8b3e4731b5c1a436e4b8529202f --hash=sha256:c8532b79afc0375a85f10433eca157d6b50f7d6990f337fa498c96cd4bfc203d! Will try again.
An error occurred while installing requests==2.22.0 --hash=sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4 --hash=sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31 --hash=sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4 --hash=sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31! Will try again.
An error occurred while installing requests-toolbelt==0.9.1 --hash=sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f --hash=sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0! Will try again.
An error occurred while installing secretstorage==3.1.1 ; sys_platform == 'linux' --hash=sha256:20c797ae48a4419f66f8d28fc221623f11fc45b6828f96bdb1ad9990acb59f92 --hash=sha256:7a119fb52a88e398dbb22a4b3eb39b779bfbace7e4153b7bc6e5954d86282a8a! Will try again.
An error occurred while installing sphinx==2.2.1 --hash=sha256:31088dfb95359384b1005619827eaee3056243798c62724fd3fa4b84ee4d71bd --hash=sha256:52286a0b9d7caa31efee301ec4300dbdab23c3b05da1c9024b4e84896fb73d79! Will try again.
An error occurred while installing sphinx-git==11.0.0 --hash=sha256:6bf9d837de108c79fb7db585ebd590fd48f4d1f830b540420d0ca675f3b9f800! Will try again.
An error occurred while installing twine==3.1.0 --hash=sha256:1a87ae3f1e29a87a8ac174809bf0aa996085a0368fe500402196bda94b23aab3 --hash=sha256:ba8ba1b39987f1c22d9162f7dd3b4668388640e5f7158c15226624f88e464836! Will try again.

Après avoir essayé diverses choses, j'ai trouvé que l'exécution de pipenv install ou pipenv sync sans environnement venv provoquait une erreur. Depuis que le hachage est affiché, j'ai essayé de supprimer Pipfile.lock pour le moment, puis j'ai exécuté pipenv install`, mais j'obtiens toujours une erreur. La situation confirmée à ce moment est la suivante.

Eh bien, qu'est-ce que c'est ...

Jetez un œil au Pipfile

Même après la suppression de l'environnement venv et de Pipfile.lock, une erreur apparaît toujours, il est donc presque certain que la cause est Pipfile. Le Pipfile à ce moment est le suivant.

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]
flake8 = "*" 
autopep8 = "*" 
isort = "*" 
autoflake = "*" 
pytest = "*" 
pytest-cov = "*" 
qiitacli = {path = "."}
twine = "*" 
sphinx = "*" 
sphinx-git = "*" 
pypandoc = "*" 

[packages]
click = ">=7.0"
qiita_v2 = ">=0.2.1"

[requires]
python_version = "3" 

[scripts]
main = "python qiitacli/client.py"

Je ne sais pas ce qui ne va pas avec mon cerveau ...

Jetez un œil au journal

J'ai essayé de regarder la sortie avec l'option -v au moment de pipenv install. J'ai été surpris qu'il y ait plus de sortie que ce à quoi je m'attendais.

Voici le journal qui semble en être la cause.

ERROR: In --require-hashes mode, all requirements must have their versions pinned with ==. These do not:
    tqdm>=4.14 from https://files.pythonhosted.org/packages/bb/62/6f823501b3bf2bac242bd3c320b592ad1516b3081d82c77c1d813f076856/tqdm-4.39.0-py2.py3-none-any.whl#sha256=5a1f3d58f3eb53264387394387fe23df469d2a3fab98c9e7f99d5c146c119873 (from twine==3.1.0->-r /tmp/pipenv-pbslpsa_-requirements/pipenv-u629hk8s-requirement.txt (line 1))    readme-renderer>=21.0 from https://files.pythonhosted.org/packages/c3/7e/d1aae793900f36b097cbfcc5e70eef82b5b56423a6c52a36dce51fedd8f0/readme_renderer-24.0-py2.py3-none-any.whl#sha256=c8532b79afc0375a85f10433eca157d6b50f7d6990f337fa498c96cd4bfc203d (from twine==3.1.0->-r /tmp/pipenv-pbslpsa_-requirements/pipenv-u629hk8s-requirement.txt (line 1))
    requests-toolbelt!=0.9.0,>=0.8.0 from https://files.pythonhosted.org/packages/60/ef/7681134338fc097acef8d9b2f8abe0458e4d87559c689a8c306d0957ece5/requests_toolbelt-0.9.1-py2.py3-none-any.whl#sha256=380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f (from twine==3.1.0->-r /tmp/pipenv-pbslpsa_-requirements/pipenv-u629hk8s-requirement.txt (line 1))
    secretstorage; sys_platform == "linux" from https://files.pythonhosted.org/packages/82/59/cb226752e20d83598d7fdcabd7819570b0329a61db07cfbdd21b2ef546e3/SecretStorage-3.1.1-py3-none-any.whl#sha256=7a119fb52a88e398dbb22a4b3eb39b779bfbace7e4153b7bc6e5954d86282a8a (from keyring>=15.1->twine==3.1.0->-r /tmp/pipenv-pbslpsa_-requirements/pipenv-u629hk8s-requirement.txt (line 1))
Exception information:
Traceback (most recent call last):
  File "/hoge/.venv/lib/python3.6/site-packages/pip/_internal/cli/base_command.py", line 153, in _main
    status = self.run(options, args)
  File "/hoge/.venv/lib/python3.6/site-packages/pip/_internal/commands/install.py", line 382, in run
    resolver.resolve(requirement_set)
  File "/hoge/.venv/lib/python3.6/site-packages/pip/_internal/legacy_resolve.py", line 208, in resolve
    raise hash_errors
pip._internal.exceptions.HashErrors: In --require-hashes mode, all requirements must have their versions pinned with ==. These do not:
    tqdm>=4.14 from https://files.pythonhosted.org/packages/bb/62/6f823501b3bf2bac242bd3c320b592ad1516b3081d82c77c1d813f076856/tqdm-4.39.0-py2.py3-none-any.whl#sha256=5a1f3d58f3eb53264387394387fe23df469d2a3fab98c9e7f99d5c146c119873 (from twine==3.1.0->-r /tmp/pipenv-pbslpsa_-requirements/pipenv-u629hk8s-requirement.txt (line 1))    readme-renderer>=21.0 from https://files.pythonhosted.org/packages/c3/7e/d1aae793900f36b097cbfcc5e70eef82b5b56423a6c52a36dce51fedd8f0/readme_renderer-24.0-py2.py3-none-any.whl#sha256=c8532b79afc0375a85f10433eca157d6b50f7d6990f337fa498c96cd4bfc203d (from twine==3.1.0->-r /tmp/pipenv-pbslpsa_-requirements/pipenv-u629hk8s-requirement.txt (line 1))
    requests-toolbelt!=0.9.0,>=0.8.0 from https://files.pythonhosted.org/packages/60/ef/7681134338fc097acef8d9b2f8abe0458e4d87559c689a8c306d0957ece5/requests_toolbelt-0.9.1-py2.py3-none-any.whl#sha256=380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f (from twine==3.1.0->-r /tmp/pipenv-pbslpsa_-requirements/pipenv-u629hk8s-requirement.txt (line 1))
    secretstorage; sys_platform == "linux" from https://files.pythonhosted.org/packages/82/59/cb226752e20d83598d7fdcabd7819570b0329a61db07cfbdd21b2ef546e3/SecretStorage-3.1.1-py3-none-any.whl#sha256=7a119fb52a88e398dbb22a4b3eb39b779bfbace7e4153b7bc6e5954d86282a8a (from keyring>=15.1->twine==3.1.0->-r /tmp/pipenv-pbslpsa_-requirements/pipenv-u629hk8s-requirement.txt (line 1))

Vous avez ajouté l'option --require-hashes lorsque vous faites pip install en interne. Je ne connaissais pas l'existence avant de voir ce journal, qui semble être mode de vérification de hachage.

ʻEn mode --require-hashes, toutes les exigences doivent avoir leurs versions épinglées avec ==. Celles-ci ne le font pasEn résumé, en mode de vérification de hachage, vous devez spécifier toutes les versions de module avec==`! !! Cela ressemble à ça. (Anglais Wakaranai)

En premier lieu, la version du module sans erreur n'est pas spécifiée dans le Pipfile, et le mystère ne fait que s'approfondir.

Jetez un œil à requirements.txt

En regardant le journal, il semble que la commande Pipenv génère un fichier équivalent à requirements.txt sous / tmp et l'exécute avec l'option -r ajoutée à la commande pip. J'ai en fait regardé le contenu de ces fichiers.

Comme méthode, appuyez simplement sur sudo cp -rf / tmp / pipenv * . à plusieurs reprises lors de l'exécution de Pipenv. Il doit y avoir un meilleur moyen, mais pour le moment.

En regardant l'un des fichiers copiés, il ressemble à ceci

twine==3.1.0 --hash=sha256:1a87ae3f1e29a87a8ac174809bf0aa996085a0368fe500402196bda94b23aab3 --hash=sha256:ba8ba1b39987f1c22d9162f7dd3b4668388640e5f7158c15226624f88e464836

Hmmm, je génère requirements.txt avec une valeur de hachage pour chaque module et je la passe à l'option -r.

J'ai vérifié la valeur de hachage, mais c'était la même valeur que le fichier réellement publié.

Je vais essayer de l'installer dans un environnement venv créé à la main en utilisant ce fichier requirements.txt.

$ echo -n ' twine==3.1.0 --hash=sha256:1a87ae3f1e29a87a8ac174809bf0aa996085a0368fe500402196bda94b23aab3 --hash=sha256:ba8ba1b39987f1c22d9162f7dd3b4668388640e5f7158c15226624f88e464836' > requirements.txt
$ python3 -m venv venv
$ ./venv/bin/pip install -r requirements.txt --require-hashes
Collecting twine==3.1.0
  Using cached https://files.pythonhosted.org/packages/74/45/1016cad7eb7cbda959a701d1dfa88b9118306677018ac3de224a6a6e7751/twine-3.1.0-py3-none-any.whl
Collecting readme-renderer>=21.0
Collecting requests-toolbelt!=0.9.0,>=0.8.0
Collecting tqdm>=4.14
Collecting requests>=2.20
Collecting keyring>=15.1
Collecting importlib-metadata; python_version < "3.8"
Requirement already satisfied: setuptools>=0.7.0 in ./venv/lib/python3.6/site-packages (from twine==3.1.0->-r requirements.txt (line 1)) (42.0.1)
Collecting pkginfo>=1.4.2
ERROR: In --require-hashes mode, all requirements must have their versions pinned with ==. These do not:
    readme-renderer>=21.0 from https://files.pythonhosted.org/packages/c3/7e/d1aae793900f36b097cbfcc5e70eef82b5b56423a6c52a36dce51fedd8f0/readme_renderer-24.0-py2.py3-none-any.whl#sha256=c8532b79afc0375a85f10433eca157d6b50f7d6990f337fa498c96cd4bfc203d (from twine==3.1.0->-r requirements.txt (line 1))
    requests-toolbelt!=0.9.0,>=0.8.0 from https://files.pythonhosted.org/packages/60/ef/7681134338fc097acef8d9b2f8abe0458e4d87559c689a8c306d0957ece5/requests_toolbelt-0.9.1-py2.py3-none-any.whl#sha256=380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f (from twine==3.1.0->-r requirements.txt (line 1))
    tqdm>=4.14 from https://files.pythonhosted.org/packages/bb/62/6f823501b3bf2bac242bd3c320b592ad1516b3081d82c77c1d813f076856/tqdm-4.39.0-py2.py3-none-any.whl#sha256=5a1f3d58f3eb53264387394387fe23df469d2a3fab98c9e7f99d5c146c119873 (from twine==3.1.0->-r requirements.txt (line 1))
    requests>=2.20 from https://files.pythonhosted.org/packages/51/bd/23c926cd341ea6b7dd0b2a00aba99ae0f828be89d72b2190f27c11d4b7fb/requests-2.22.0-py2.py3-none-any.whl#sha256=9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31 (from twine==3.1.0->-r requirements.txt (line 1))
    keyring>=15.1 from https://files.pythonhosted.org/packages/b1/08/ad1ae7262c8146bee3be360cc766d0261037a90b44872b080a53aaed4e84/keyring-19.2.0-py2.py3-none-any.whl#sha256=f5bb20ea6c57c2360daf0c591931c9ea0d7660a8d9e32ca84d63273f131ea605 (from twine==3.1.0->-r requirements.txt (line 1))
    importlib-metadata; python_version < "3.8" from https://files.pythonhosted.org/packages/f6/d2/40b3fa882147719744e6aa50ac39cf7a22a913cbcba86a0371176c425a3b/importlib_metadata-0.23-py2.py3-none-any.whl#sha256=d5f18a79777f3aa179c145737780282e27b508fc8fd688cb17c7a813e8bd39af (from twine==3.1.0->-r requirements.txt (line 1))
    pkginfo>=1.4.2 from https://files.pythonhosted.org/packages/e6/d5/451b913307b478c49eb29084916639dc53a88489b993530fed0a66bab8b9/pkginfo-1.5.0.1-py2.py3-none-any.whl#sha256=a6d9e40ca61ad3ebd0b72fbadd4fba16e4c0e4df0428c041e01e06eb6ee71f32 (from twine==3.1.0->-r requirements.txt (line 1))

Oh! Je l'ai reproduit!

Mais l'erreur se trouve dans un module différent de celui décrit dans requirements.txt ...

Dans ce mode de vérification de hachage, il est nécessaire de décrire tous les packages dépendants en spécifiant la version. Mais pourquoi n'obtenez-vous pas une erreur lorsque vous faites normalement pipenv install?

Qu'est-ce que --no-deps

Après avoir vérifié le journal pendant un moment, j'ai trouvé qu'il avait une option --no-deps lors de l'installation avec pip quand il fonctionne correctement.

$ ['/hoge/.venv/bin/pip', 'install', '--verbose', '--upgrade', '-r', '/tmp/pipenv-9owwlzhi-requirements/pipenv-65yqxf03-requirement.txt', '-i', 'https://pypi.org/simple', '--require-hashes']
$ ['/hoge/.venv/bin/pip', 'install', '--verbose', '--upgrade', '--no-deps', '-r', '/tmp/pipenv-5dvxlnyt-requirements/pipenv-pvatvj5c-requirement.txt', '-i', 'https://pypi.org/simple', '--require-hashes']

Oh, ça ressemble à ça!

--no-deps est Ne pas installer les dépendances de paquet . En d'autres termes, c'est une option qui n'installe pas les paquets dépendants. Naruhode Si tel est le cas, le fichier requirements.txt mentionné précédemment semble fonctionner normalement.

$ ./venv/bin/pip install -r requirements.txt --require-hashes --no-deps 
Collecting twine==3.1.0
  Using cached https://files.pythonhosted.org/packages/74/45/1016cad7eb7cbda959a701d1dfa88b9118306677018ac3de224a6a6e7751/twine-3.1.0-py3-none-any.whl
Installing collected packages: twine
Successfully installed twine-3.1.0

l'a fait.

La cause a été appréhendée petit à petit.

Le seul mystère restant est ** Pourquoi n'avez-vous pas ajouté l'option --no-deps **?

La dernière clé est modifiable

À la fin, je n'ai pas d'autre choix que de lire la source de Pipenv.

https://github.com/pypa/pipenv

Voyons où la commande pip install ... est réellement exécutée lorsque pipenv install est exécutée.

L'endroit où la commande pip est réellement exécutée était la fonction pip_install dans pipenv / core.py. Il y avait divers ordres d'appel tels que do_install-> do_init-> do_install_dependencies-> batch_install-> pip_install, mais ... En conclusion, la partie suivante de la fonction batch_install a été marquée pour savoir s'il fallait ou non ajouter l'option --no-deps.

        if not PIPENV_RESOLVE_VCS and is_artifact and not dep.editable:
            install_deps = True 
            no_deps = False

dep est une classe qui contient des informations sur les modules à installer. Pas PIPENV_RESOLVE_VCS, mais ʻis_artifact, et le module n'est pas ʻeditable ...

Je ne comprends pas du tout

D'une manière ou d'une autre, "les modules installés à partir des sources qui ne sont pas marqués comme modifiables" semblent être liés à l'ajout de --no-deps. Après pipenv install -h, il y avait quelque chose comme ça.

$ pipenv install -h
Abréviation
  -e, --editable TEXT      An editable python package URL or path, often to a
                           VCS repo.

Ah ,,,

Solution

Regardons à nouveau le Pipfile qui a causé l'erreur.

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]
flake8 = "*"
autopep8 = "*"
isort = "*"
autoflake = "*"
pytest = "*"
pytest-cov = "*"
qiitacli = {path = "."}
twine = "*"
sphinx = "*"
sphinx-git = "*"
pypandoc = "*"

[packages]
click = ">=7.0"
qiita_v2 = ">=0.2.1"

[requires]
python_version = "3"

[scripts]
main = "python qiitacli/client.py"

Oui la cause est

qiitacli = {path = "."}

C'était ce type.

J'avais l'habitude de faire pipenv install . lors de l'installation d'un module en cours de développement localement, mais c'était un problème. La bonne réponse est «pipenv install -e.». Le Pipfile résultant ressemble à ceci.

qiitacli = {editable = true,path = "."}

Il a un indicateur modifiable.

Dans cet état, l'installation est terminée normalement.

Résumé

J'avais l'habitude de le mettre correctement avec l'option -e, mais après avoir réalisé que je pouvais l'installer sans l'option, j'ai décidé de l'installer tel quel. (Peut-être)

À propos, il était fermement écrit dans le document officiel. https://pipenv-ja.readthedocs.io/ja/translate-ja/basics.html#editable-dependencies-e-g-e

Au moins, comprenons la signification des options que nous utilisons. moi même.

Recommended Posts

L'histoire de l'erreur de hachage est apparue lors de l'utilisation de Pipenv
Une histoire qui était pratique lorsque j'ai essayé d'utiliser le module d'adresse IP python
[Linux / GCP] Traitement des erreurs survenues lors de l'utilisation de la commande Git
Une histoire quand un répertoire est bogué avec la commande django-admin start project dans un environnement virtuel utilisant Pipenv
Une histoire addictive lors de l'utilisation de tensorflow sur Android
Générez des valeurs de hachage à l'aide de la méthode HMAC.
C'est une histoire de ferroutage sur le service qui renvoie "Nyan" lorsque vous appuyez sur ping
Une histoire qui a échoué lors de la tentative de suppression du suffixe d'une chaîne avec rstrip
Une histoire bloquée lors de la tentative de mise à niveau de la version Python avec GCE
Une histoire qui a eu du mal avec l'ensemble commun HTTP_PROXY = ~
Une histoire sur une erreur lorsque PyInstaller est utilisé dans un programme qui utilise googleapiclient
Il y a un modèle que le programme ne s'est pas arrêté lors de l'utilisation du thread Python
Une histoire qui a analysé la livraison de Nico Nama.
Une histoire qui facilite l'estimation de la surface habitable à l'aide d'Elasticsearch et de Python
Une histoire qui a trébuché lorsque j'ai créé un bot de chat avec Transformer
J'ai eu une erreur de valeur lors de l'utilisation de JUMAN ++ avec PyKNP
Une histoire sur l'installation de matplotlib à l'aide de pip avec une erreur
L'histoire de la création d'une base de données à l'aide de l'API Google Analytics
Lorsque vous utilisez la propriété, utilisez une classe qui hérite d'un objet (classe de style nouveau)
Une histoire qui n'a pas fonctionné lorsque j'ai essayé de me connecter avec le module de requêtes Python
Lors de l'incrémentation de la valeur d'une clé qui n'existe pas
L'histoire selon laquelle l'environnement Homebrew a été époustouflé lors de l'installation d'Anaconda
Une histoire que j'ai corrigée lorsque j'ai obtenu le journal Lambda de Cloudwatch Logs
Précautions lors de l'utilisation d'une liste ou d'un dictionnaire comme argument par défaut
Une histoire sur une erreur de construction dans une bibliothèque partagée qui fait référence à libusb
[Ev3dev] Créez un programme qui capture LCD (écran) en utilisant python
L'histoire de la création d'un site qui répertorie les dates de sortie des livres
L'histoire selon laquelle le gardien était confiné lorsque le laboratoire a été converti à l'IoT
L'histoire de la création d'un module qui ignore le courrier avec python
Erreur lors de l'appel du module tkinter dans un éditeur de texte ne fonctionne pas comme prévu
L'histoire de la création d'un slackbot qui génère un gif ou un png lorsque vous envoyez le code de traitement
Un mémorandum lors de l'utilisation d'une belle soupe
Précautions lors de l'utilisation de la fonction urllib.parse.quote
L'histoire de l'utilisation de la réduction de Python
L'histoire de l'exportation d'un programme
Une histoire qui visualise le présent de Qiita avec Qiita API + Elasticsearch + Kibana
L'histoire du développement d'une application WEB qui génère automatiquement des copies de capture [MeCab]
Estimer la probabilité qu'une pièce apparaisse en utilisant MCMC
L'histoire de la création d'un package qui accélère le fonctionnement de Juman (Juman ++) & KNP
Une note utile lors de l'utilisation de Python après une longue période
Une histoire qui a souffert d'une différence de système d'exploitation lors de la tentative d'implémentation d'un article