poetry下载包报hash错误原因排查
问题
执行 poetry install 的时候出现 sha256 校验失败
排查
猜测 1:是不是 pypi 源出问题了
因为我用的是自建的 pypi 代理,https://github.com/EpicWink/proxpi/ 能将包缓存到本地,提高下载速度。
先换掉本地代理,直接走官方源 pypi.org 试试,哎,正常了。
可是官方源慢啊,必须得走 pypi 代理呀,所以一定要找出来 pypi 代理出啥问题了
猜测 2: 难道是 pypi 上的包不对?
直接去代理的地址找到对应
1 | $ find . | grep colored | xargs sha256sum |
看 hash 值也没问题,跟 pypi.org 上的一样
猜测 3:说不定是 poetry 的本地缓存出问题了
先是调用了一下 poetry 自己的命令,清空自身缓存
1 | $ poetry cache clear . --all |
没效果。还是报一样的错误
猜测 4:说不定代理没有读本地文件,直接读的内存
先重启一下代理服务,下包试试
1 | $ wget -q https://pypiproxy.example.com/index/colored/colored-1.4.4.tar.gz -O- | shasum -a256 |
看起来没什么问题,hash 正确。
再试试 poetry 清缓存,然后 install,依然报错。
猜测 5:poetry 莫非还有没清的缓存
直接翻源码,一路找到代码下载的位置
https://github.com/python-poetry/poetry/blob/2b50120c86ae72781357411342f2feda0a4e2713/src/poetry/utils/helpers.py#L141
增加一行
1 | print("Download", url, dest) |
最后发现,确实下载了。但就是下载的文件 sha 值不对。
解压包试试呢 tar -xzvf colored-1.4.4.tar.gz,简单的看了一下,内容是对的。没什么问题。
猜测 6:难道是 requests 出问题了
这个想法我自己都觉的离谱,requests 怎么可能出问题
让 GPT 写一个通过 requests 下载代码并校验 sha256 的功能看看, GPT 效率非常的高,很快就写好了
1 | import requests |
执行后输出什么呢
1 | $ python download.py |
看来 requests 有问题,可为什么文件是一样的呢?太奇怪了。
让 GPT 重写一下代码,将 requests 替换为 urllib 下载。
没想到下载到的文件 hash 竟然又对了。看来问题就出在 requests 上,但是就是不知道为什么。问 GPT4 也没给出什么有用的答案。
既然如此,代理上的那个 colored-1.4.4.tar.gz 文件,直接改成 hello 文本。我倒要看看 requests 怎么整出来不同的文件 hash
1 | echo hello > colored-1.4.4.tar.gz |
视角转到自己的电脑上,执行命令,出现了。下载报错
1 | $ python download.py |
到这里终于看到了成功的曙光了。问题原因出在 requests 下载的时候会自己 decode 呀。
之前下载的那个 colored-1.4.4.tar.gz 用 file 命令看看
1 | $ file colored-1.4.4.tar.gz |
我擦,果然是 tar 文件。破案了,原来是,requests 直接帮忙把 tar.gz 解压了成 tar 文件了,但是文件名没改。难怪外表看起来一样,但是 hash 一直不对。
结论
requests 库下载文件的时候,会自动把 tar.gz 解压了成 tar 文件了,导致 hash 一直不对。更换 urllib 获取直接 curl 请求的下载就是正确的。
问题修复
修复方案 1
既然是 requests 自动解压了,那就想办法把 Content-Encoding: gzip 从服务端先去掉吧。让 requests 不自动解压。
查看了一下我那个代理的源码文档。有一个配置看起来可以。
再看 flask 的源码,发现只要设置了 mimetype,Content-Encoding 就不会设置。
修改完之后,重启 proxi 代理测试一下
1 | $ http HEAD https://pypiproxy.example.com/index/colored/colored-1.4.4.tar.gz |
这里看到 Content-Encoding 不见了。
再次测试一下 poetry,先清缓存再 poetry install。终于不报错误了。完美
修复方案 2
改一下 poetry,让其使用 requests 下载的时候不再自动解码
1 | # Ref: https://stackoverflow.com/questions/18364193/requests-disable-auto-decoding |
poetry下载包报hash错误原因排查
https://blog.codeskyblue.xyz/2023/11/22/souq08lf43izvfcr.html