71

When I do pip freeze I get the packages I've explicitly installed plus those packages that are dependencies of those packages.

For example:

$ pip install fabric
...
$ pip freeze
Fabric==1.0.1
paramiko==1.7.6
pycrypto==2.3

Ok fine but then I move to install this requirements.txt on another environment with pip install I'd get the same result with the last 2 lines removed.

So my question is: how I can I create the most simplified requirements.txt where all calculable dependencies are not shown?

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Tom Viner
  • 6,655
  • 7
  • 39
  • 40

4 Answers4

125

Now there is (disclaimer: I did it).

All you need is to install pip-chill from PyPI and run pip-chill from your Python environment.

If you are feeling adventurous and don't want to pin versions (or want to use pip-compile), you can use pip-chill --no-version and it'll give you the minimal requirements for your current environment.

https://github.com/rbanffy/pip-chill

rbanffy
  • 2,319
  • 1
  • 16
  • 27
  • 2
    This is just what I asked for! Thanks. – Tom Viner Oct 19 '16 at 18:35
  • 2
    You are my hero! Been looking for this for years ;-) – sheats Sep 14 '19 at 01:36
  • 1
    Note pip-chill requires pip>=10. On pip==9 it raises "No module named pip._internal". Fixed within the virtualenv by `pip install --upgrade pip` – krubo Oct 09 '19 at 10:22
  • 1
    Thank you for this!! – tmhs May 05 '20 at 17:23
  • 1
    Saved my deployment. Thank You! – omer Jan 18 '21 at 19:43
  • 4
    This should be merged into pip itself. Thanks! – ospider Apr 11 '21 at 07:31
  • 1
    Thank you so much for this. Have you tried to contributing this to pip itself? – Jylpah Jan 16 '23 at 16:46
  • 1
    FYI: The tool has a bug that makes it so packages won't show up if they're a dependency of another top-level package https://github.com/rbanffy/pip-chill/issues/49 (getting it with Flask) – GammaGames Jan 19 '23 at 23:31
  • Thanks, @GammaGames. I think I missed the issue and should have been much less slow at responding. I think I have a good solution, but I'd appreciate your input and the one from others who identified the issue. – rbanffy Jan 23 '23 at 15:50
  • 2
    This is nice. Want to add a valuable improvement? Add the ability to pin minimum and less than next major, meaning, turn `pkg==1.2.3` into `pkg>=1.2.3,<2` – Wyrmwood Apr 12 '23 at 22:50
  • @Wyrmwood: That's an idea - compute the intersection of all restrictions about a certain package. I'm not sure, though, this information is available after the package is installed. We should continue this conversation on GitHub. – rbanffy Apr 13 '23 at 23:48
12

There is no way to create "the most simplified requirements.txt" with pip - and I don't know if you would need it in this case.

It is good to have all packages in the requirements.txt, because you are sure about what dependencies versions work with your environment.

Think about paramiko getting updated, and breaking backwards compatibilities: you would have problems.

Hugo Lopes Tavares
  • 28,528
  • 5
  • 47
  • 45
  • 10
    I don't think `all packages` is correct. Since `pip install -r requirements.txt` will install dependency automatically, we just need the root/original packages. – Nam G VU Oct 05 '16 at 12:36
  • 2
    @NamGVU: I said it's "good to have all packages," not that it's a must. It's a good practice to specify all packages because you have better control of your environment. Think about a given package A that depends on B==1.0.0 and B depends on C (any version). The Package A only has to require B==1.0, but if for any reason package C is updated in a backward incompatible way, package A might have trouble (because it didn't specify what version of package C is guaranteed to work). Thus, it's **safer** for A to specify both B==1.0.0 **and** a version of C that was tested and you know it works. – Hugo Lopes Tavares Oct 06 '16 at 16:05
  • The correct/compatible vesion of C is defined by B not A; and that works automatically by pip. Thanks for sharing anyway. – Nam G VU Oct 06 '16 at 16:33
  • 4
    @NamGVU: the Python world isn't perfect and a lot of times people don't specify strict versions for their immediate dependencies. I've seen this problem happen many times. One case that comes to mind is when `python-statsd` **mistakenly** specified `mock` (no pinned version) as a dependency and all of a sudden the newest version of `mock` requires a different version of `setuptools`. Some of my servers broke because they used `python-statsd==1.6.0` and didn't specify the full hierarchy of dependencies. See https://git.io/vPWIW and https://github.com/testing-cabal/mock/issues/261 – Hugo Lopes Tavares Oct 06 '16 at 19:05
  • Thanks for great sharing with such specific sample on `python-statsd`; and then, I totally agree to attach the version here. I also agree there is something wrong with `pip` developer team. – Nam G VU Oct 07 '16 at 01:43
  • By the way, I love Python and want to join to make it perfect. Where we can **read the dependency definition** for one pip package @hugotavares? – Nam G VU Oct 07 '16 at 01:45
7

I think the simply way to remove version is cut -d"=" -f1 after having run pip freeze.

pip3 freeze | cut -d"=" -f1 
Tms91
  • 3,456
  • 6
  • 40
  • 74
haulpd
  • 257
  • 2
  • 6
4

pipdeptree is another option.

It produces full requirements.txt (with pipdeptree -f) like this:

jupyter==1.0.0
  ipykernel==5.4.3
    ipython==7.19.0
      backcall==0.2.0
      decorator==4.4.2
      jedi==0.17.2
        parso==0.7.1

This file serves two purposes:

  • Used as a traditional requirements.txt fed to pip install;
  • Used as a developer-friendly packages list (like the one created by pip-chill) simply with grep '^\w' requirements.txt.
Leo
  • 1,710
  • 2
  • 26
  • 29