`nix shell` for python packages?

I am running Nix 2.4. I know how to use, e.g., nix run and nix shell for packages in the nixpkgs flake (e.g., nix run nixpkgs#gimp, et al.). But I cannot figure out how to do this for Python.

Simple example that just tripped me up–I want to use the Python requests package in an ad hoc environment. I tried nix shell nixpkgs#python38Packages.requests, which looks like it worked, but then:

$ python
Python 3.8.11 (default, Jun 28 2021, 10:57:31)
[GCC 10.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'requests'

What is the right way to do this?

EDIT: I forgot to mention–it seems the old-school way to do this is nix-shell -p python38Packages.requests, which works (I am able to import requests in a Python shell). My question can be stated another way as: what is the new-school way to do this?


1 Like

nix shell doesn’t execute shellHooks, which is how python38Packages.requests exports a PYTHONPATH with itself and it’s dependencies.

You could use nix develop with a derivation which has requests as a dependency. But AFAIK, there is not an exact replacement for all that nix-shell -p provided.


mach-nix has a convenient way of doing this in the brave new flakes world:

nix shell github:DavHau/mach-nix#gen.python.requests

If you need more packages, just add .<name> for each to the end.

Can’t explicitly set the python version with it, but if you’d like to pin down more specifics you should probably make a devShell anyway.

That said, it’s a bit of a shame that we’re missing this in upstream nix sub-commands :expressionless:

1 Like

Thanks for the explanation.

Is this worth filing an issue? Or does, e.g., Flakes UX: make it easy to evaluate an arbitrary expression in a context of a flake · Issue #5567 · NixOS/nix · GitHub cover this already?

I think the behavior was intentional. nix shell usually being intended to add a command to a child shell.

Handling of python is kind of hard, as a lot of it’s behaviors are not representative in other ecosystem.

For python -c 'import requests' to work, you either need to:

  • Have the requests package, and its transitive dependencies co-located in the same site-packages (which python3.withPackages does)
  • Or set $PYTHONPATH to include requests and its transitive dependencies (what the python3Packages.setuptoolsBuildHook does)
1 Like

Another idea: Using requests latest for python39 on Nix

nix develop 'github:on-nix/python#"requests-latest-python39"'
1 Like