You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
PIP cache should cache the installed packages as well #330
Description:
Currently, setup-python caches only the ~/.cache/pip directory to avoid redownloads. However, it doesn't cache the installed packages. As some package have lengthy installation steps, this leads to delays in builds.
would be also nice to follow https://github.com/actions/cache#outputs and provide an output cache-hit so we can if: steps.[id]. cache-hit != 'true' to avoid calling pip altogether.
Reacted by Ricardo de Matos, Jeffrey Allman, Adam J. Stewart, Adriano Carmezim, Girish Ravi and Santiago Fraire Willemoes
This pattern affects more languages (actions/setup-node works the same - only caches downloads, not installs) - would love to see a general consensus towards caching installs, not tarballs (perhaps behind a flag/attribute for future compat cache: pip-install).
for pip I think it makes even more sense as there are no postinstall actions... with setup-node I'm also caching the node_modules instead of the packages, but it "broke" some flows where there was a postinstall script to configure other things (like pre-build some typescript scripts). The solution is simple, just run that script manually (or in my case, cache the built scripts)... but not "one size fits all".
For pip AFAIR there are no postinstall scripts, then this would not be an issue.
For pip AFAIR there are no postinstall scripts, then this would not be an issue.
I'm experimenting with this at the moment and caching site-packages (read: pip output) isn't straightforward either; for instance binary wrappers (black, ..) won't work (python -m black works fine tho). Might be one of thos YMMV cases that makes it hard to standardize for everyone.
would be also nice to follow https://github.com/actions/cache#outputs and provide an output cache-hit so we can if: steps.[id]. cache-hit != 'true' to avoid calling pip altogether.
Hey, this feature was merged today and should be a part of the near-future release
Reacted by Gustavo Sverzut Barbieri and Girish Ravi
but the cache-hit is just for the packages, not the installation, right? IOW: do I still need to call pip install?
Oh you're talking pip. Well yeah, then you'll have to wait for this action to support caching venv's out of the box. It's a case for pipenv and poetry though. The best this for now is to manually cache
I was creating a python venv and then caching that directory, however I hit an issue where that was broken once restored (behaviour was inconsistent).
I currently have a job that takes ~6 min to complete, 4 min of which is installation of pip packages. An effective caching of installed packages would be a great boost.
I was creating a python venv and then caching that directory, however I hit an issue where that was broken once restored (behaviour was inconsistent).
I currently have a job that takes ~6 min to complete, 4 min of which is installation of pip packages. An effective caching of installed packages would be a great boost.
Could you share the workflow so the people can take a look at it? I think it's possible to hack around while this feature is not here
I wonder if it's actually worth it.
Here I cached the content of ${{ env.pythonLocation }}/lib/site-packages and ${{ env.pythonLocation }}/Scripts using actions/cache:
This resulted in significantly faster installation times, which could likely be further improved by only caching the site-packages directory:
Python
Linux
macOS
Windows
3.10
38s
39s
4m 11s
3.9
53s
45s
4m 20s
3.8
1m 2s
1m 15s
1m 21s
Apparently slower Windows caching is a known issue: actions/cache#752.
So yes, if setup-python also cached installed packages, that would be awesome!
Reacted by John Belmonte, CoreyGaunt, Kaspar Peterson, Wen Wei Tseng, Agriya Khetarpal, AJ Bowen, Sander van Rijn, Abdullah ;), Heiner, Wesley and 15 more
Reacted by Julian Badillo, Eloy Adonis Colell, Abderraouf Djaber and Jingchao (Perry) Zhong
In hindsight, this is a bad idea, many tools like black or flake8 also install files into bin so we'll at least need to cache bin too.
I addressed this point a while ago (above) - recap here:
I'm experimenting with this at the moment and caching site-packages (read: pip output) isn't straightforward either; for instance binary wrappers (black, ..) won't work (python -m black works fine tho). Might be one of thos YMMV cases that makes it hard to standardize for everyone.
So, instead of invoking black, do python -m black.
That's a decent workaround, but I don't think it's realistic to expect all users to change how they invoke other steps later in their workflow. I think we would have to cache bin too. Possibly everything. Bonus of caching everything is that we have to install Python from a cache anyway.
That's a decent workaround, but I don't think it's realistic to expect all users to change how they invoke other steps later in their workflow. I think we would have to cache bin too. Possibly everything. Bonus of caching everything is that we have to install Python from a cache anyway.
Most definitely not a catch-all! To be honest I'm not confident there's a straightforward solution..
The workaround from @adamjstewart seems to work wonders indeed ! But I think a standard implementation from this repository would be a great addition. Any updates on it from the dev team ?
Install times without caching vary quite a bit by OS and Python version:
Python Linux macOS Windows
3.10 2m 30s 2m 23s 5m 4s
3.9 2m 50s 4m 50s 5m 49s
3.8 2m 29s 2m 12s 3m 19s
We first tried using the cache feature of setup-python:
Not only do install times not significantly improve, in many cases it's actually worse!
Python Linux macOS Windows
3.10 2m 42s 1m 53s 5m 50s
3.9 2m 50s 2m 11s 5m 46s
3.8 2m 39s 3m 21s 2m 35s
Finally, we tried the setup proposed in this blog that manually caches the entire Python installation:
This resulted in significantly faster installation times, which could likely be further improved by only caching the site-packages directory:
Python Linux macOS Windows
3.10 38s 39s 4m 11s
3.9 53s 45s 4m 20s
3.8 1m 2s 1m 15s 1m 21s
Apparently slower Windows caching is a known issue: actions/cache#752.
So yes, if setup-python also cached installed packages, that would be awesome!
This right here has been a life saver for me - I toiled over this caching for so long, but this got me there!! Thank you so so so much!!
Reacted by Zhihao Zhang
Reacted by Adam J. Stewart, Wen Wei Tseng and Rick Staa
In hindsight, this is a bad idea, many tools like black or flake8 also install files into bin so we'll at least need to cache bin too.
@adamjstewart, thanks for your awesome post, it really reduced my build times.
It's definitely possible to achieve your idea of caching only the necessary items instead of the entire python build by caching the site-packages and bin (in order to get executable packages like black, ruff, etc..). In my case, my two dependency files are classic pip-tools dev-requirements.txt and requirements.txt.
@adamjstewart Thanks for the cache example, it really helps. :-)
I have one more suggestion that I decided to use, because I want to avoid downloading all pip dependencies everytime any of them changes - to introduce a second cache just for pip cache.
The key is on the cache step standing before the actions/setup-python. It will restored the cache, includes: binaries and libraries then parse into path. actions/setup-python sees x64.complete 0-byte file existed under path so will not download Python binary again.
The console output with cache should be
Cache restored successfully
Cache restored from key: /opt/hostedtoolcache/Python/3.11.6/x64-95421aa4e4a3b4024058ea1f527f5a724a65d3408f2a8c64daad58bfa48fa33d
...
Run actions/setup-python@v4
Successfully set up CPython (3.11.6)
...
Run pip install -r requirements.txt
Requirement already satisfied: requests==2.25.1 in /opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages (from -r requirements.txt (line 2)) (2.25.1)
Requirement already satisfied: pyyaml==6.0.1 in /opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages (from -r requirements.txt (line 3)) (6.0.1)
Finally, we tried the setup proposed in this blog that manually caches the entire Python installation:
This works pretty well after the cache is populated, however, populating the cache for me seems to take 13m with the deps we have, not just on initial creation, but also when the cache is busted
Has anyone had any luck with a similar approach that will handle partial restores more cleanly (without using pipenv, which is what I've typically done for caching in the past)
Activity
nikita-bykov commentedon Feb 4, 2022
Hello @crabhi, thanks for your request!
We will look at it.
barbieri commentedon Mar 24, 2022
would be also nice to follow https://github.com/actions/cache#outputs and provide an output
cache-hitso we canif: steps.[id]. cache-hit != 'true'to avoid callingpipaltogether.barbieri commentedon Mar 24, 2022
which is done at https://github.com/actions/cache/blob/2d8d0d1c9b41812b6fd3d4ae064360e7d8762c7b/src/utils/actionUtils.ts#L25-L27 and https://github.com/actions/cache/blob/main/src/restore.ts#L55
jbergstroem commentedon Mar 29, 2022
This pattern affects more languages (
actions/setup-nodeworks the same - only caches downloads, not installs) - would love to see a general consensus towards caching installs, not tarballs (perhaps behind a flag/attribute for future compatcache: pip-install).barbieri commentedon Mar 29, 2022
for
pipI think it makes even more sense as there are nopostinstallactions... withsetup-nodeI'm also caching thenode_modulesinstead of the packages, but it "broke" some flows where there was apostinstallscript to configure other things (like pre-build some typescript scripts). The solution is simple, just run that script manually (or in my case, cache the built scripts)... but not "one size fits all".For pip AFAIR there are no postinstall scripts, then this would not be an issue.
jbergstroem commentedon Mar 29, 2022
I'm experimenting with this at the moment and caching site-packages (read: pip output) isn't straightforward either; for instance binary wrappers (black, ..) won't work (
python -m blackworks fine tho). Might be one of thos YMMV cases that makes it hard to standardize for everyone.dhvcc commentedon Apr 5, 2022
Hey, this feature was merged today and should be a part of the near-future release
barbieri commentedon Apr 5, 2022
but the
cache-hitis just for the packages, not the installation, right? IOW: do I still need to callpip install?dhvcc commentedon Apr 5, 2022
Oh you're talking
pip. Well yeah, then you'll have to wait for this action to support caching venv's out of the box. It's a case for pipenv and poetry though. The best this for now is to manually cachebelm0 commentedon Apr 16, 2022
I have a case where building packages for pypy (grpcio, grpcio-tools) takes about 6 minutes-- it's way too slow to introduce a matrix.
If anyone has a manual example using actions/cache, please share it.
rashidnhm commentedon May 9, 2022
I was creating a python venv and then caching that directory, however I hit an issue where that was broken once restored (behaviour was inconsistent).
I currently have a job that takes ~6 min to complete, 4 min of which is installation of pip packages. An effective caching of installed packages would be a great boost.
dhvcc commentedon May 10, 2022
Could you share the workflow so the people can take a look at it? I think it's possible to hack around while this feature is not here
9 remaining items
CI: always run pip install, even when cache found
Avasam commentedon Nov 24, 2022
I wonder if it's actually worth it.
Here I cached the content of
${{ env.pythonLocation }}/lib/site-packagesand${{ env.pythonLocation }}/Scriptsusingactions/cache:No caching:

Caching, no cache hit (+1m):

Caching, cache hit (+18s):

dhvcc commentedon Dec 2, 2022
@Avasam possibly at least less strain on pypi. Also we should test small and big amounts of dependencies
adamjstewart commentedon Feb 5, 2023
Just wanted to add an anecdote of my own experience. TorchGeo has a long list of dependencies:
Install times without caching vary quite a bit by OS and Python version:
We first tried using the cache feature of setup-python:
Not only do install times not significantly improve, in many cases it's actually worse!
Finally, we tried the setup proposed in this blog that manually caches the entire Python installation:
This resulted in significantly faster installation times, which could likely be further improved by only caching the site-packages directory:
Apparently slower Windows caching is a known issue: actions/cache#752.
So yes, if setup-python also cached installed packages, that would be awesome!
adamjstewart commentedon Feb 7, 2023
In hindsight, this is a bad idea, many tools like black or flake8 also install files into bin so we'll at least need to cache bin too.
jbergstroem commentedon Feb 7, 2023
I addressed this point a while ago (above) - recap here:
So, instead of invoking
black, dopython -m black.adamjstewart commentedon Feb 7, 2023
That's a decent workaround, but I don't think it's realistic to expect all users to change how they invoke other steps later in their workflow. I think we would have to cache bin too. Possibly everything. Bonus of caching everything is that we have to install Python from a cache anyway.
jbergstroem commentedon Feb 7, 2023
Most definitely not a catch-all! To be honest I'm not confident there's a straightforward solution..
Seluj78 commentedon Feb 22, 2023
The workaround from @adamjstewart seems to work wonders indeed ! But I think a standard implementation from this repository would be a great addition. Any updates on it from the dev team ?
CoreyGaunt commentedon Apr 7, 2023
This right here has been a life saver for me - I toiled over this caching for so long, but this got me there!! Thank you so so so much!!
nicklausbrown commentedon Aug 28, 2023
@adamjstewart, thanks for your awesome post, it really reduced my build times.
It's definitely possible to achieve your idea of caching only the necessary items instead of the entire python build by caching the site-packages and bin (in order to get executable packages like black, ruff, etc..). In my case, my two dependency files are classic pip-tools
dev-requirements.txtandrequirements.txt.Finally I run the pip install step conditionally based on successful cache hits with the following:
Mileage can vary for small dependency lists based on the cache restore network speed.
harpener commentedon Sep 7, 2023
@adamjstewart Thanks for the cache example, it really helps. :-)
I have one more suggestion that I decided to use, because I want to avoid downloading all pip dependencies everytime any of them changes - to introduce a second cache just for pip cache.
itsme2980 commentedon Oct 11, 2023
Unfortunately, the built-in cache functionality only supports dependencies downloaded by package manger, not the whole Python as expected.
I made an example to cache both of download libraries and binaries (
python+ package manager likepip) viaactions/cacheThe key is on the
cachestep standing before theactions/setup-python. It will restored the cache, includes: binaries and libraries then parse intopath.actions/setup-pythonseesx64.complete0-byte file existed underpathso will not download Python binary again.The console output with cache should be
Note: the above ^ testing on self-host runner.
wyardley commentedon Oct 27, 2023
This works pretty well after the cache is populated, however, populating the cache for me seems to take 13m with the deps we have, not just on initial creation, but also when the cache is busted
This is running
Has anyone had any luck with a similar approach that will handle partial restores more cleanly (without using pipenv, which is what I've typically done for caching in the past)