Pip not found by python39 in nix-shell

I have a simple shell.nix for a python project I’m working on:

with import <nixpkgs> {};
with pkgs.python39Packages;
buildPythonPackage rec {
  name = "my-package";
  src = ./my-package;
  buildInputs = [ pkgs.python39 pip ];
  propagatedBuildInputs = [ pkgs.python39 pycryptodome setuptools pip ];
}

When I run nix-shell I get the following stack trace:

--- Logging error ---
Traceback (most recent call last):
  File "/nix/store/zhbvq21cnf49s43msvbg0rga3f3zigpz-python3.9-pip-22.2.2/lib/python3.9/site-packages/pip/_internal/utils/logging.py", line 177, in emit
    self.console.print(renderable, overflow="ignore", crop=False, style=style)
  File "/nix/store/zhbvq21cnf49s43msvbg0rga3f3zigpz-python3.9-pip-22.2.2/lib/python3.9/site-packages/pip/_vendor/rich/console.py", line 1673, in print
    extend(render(renderable, render_options))
  File "/nix/store/zhbvq21cnf49s43msvbg0rga3f3zigpz-python3.9-pip-22.2.2/lib/python3.9/site-packages/pip/_vendor/rich/console.py", line 1305, in render
    for render_output in iter_render:
  File "/nix/store/zhbvq21cnf49s43msvbg0rga3f3zigpz-python3.9-pip-22.2.2/lib/python3.9/site-packages/pip/_internal/utils/logging.py", line 134, in __rich_console__
    for line in lines:
  File "/nix/store/zhbvq21cnf49s43msvbg0rga3f3zigpz-python3.9-pip-22.2.2/lib/python3.9/site-packages/pip/_vendor/rich/segment.py", line 249, in split_lines
    for segment in segments:
  File "/nix/store/zhbvq21cnf49s43msvbg0rga3f3zigpz-python3.9-pip-22.2.2/lib/python3.9/site-packages/pip/_vendor/rich/console.py", line 1283, in render
    renderable = rich_cast(renderable)
  File "/nix/store/zhbvq21cnf49s43msvbg0rga3f3zigpz-python3.9-pip-22.2.2/lib/python3.9/site-packages/pip/_vendor/rich/protocol.py", line 36, in rich_cast
    renderable = cast_method()
  File "/nix/store/zhbvq21cnf49s43msvbg0rga3f3zigpz-python3.9-pip-22.2.2/lib/python3.9/site-packages/pip/_internal/self_outdated_check.py", line 130, in __rich__
    pip_cmd = get_best_invocation_for_this_pip()
  File "/nix/store/zhbvq21cnf49s43msvbg0rga3f3zigpz-python3.9-pip-22.2.2/lib/python3.9/site-packages/pip/_internal/utils/entrypoints.py", line 58, in get_best_invocation_for_this_pip
    if found_executable and os.path.samefile(
  File "/nix/store/4h7n4af8z6bqjhisn5xf1h1bljan44yk-python3-3.9.15/lib/python3.9/genericpath.py", line 101, in samefile
    s2 = os.stat(f2)
FileNotFoundError: [Errno 2] No such file or directory: '/nix/store/4h7n4af8z6bqjhisn5xf1h1bljan44yk-python3-3.9.15/bin/pip'
Call stack:
  File "/nix/store/4h7n4af8z6bqjhisn5xf1h1bljan44yk-python3-3.9.15/lib/python3.9/runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/nix/store/4h7n4af8z6bqjhisn5xf1h1bljan44yk-python3-3.9.15/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/nix/store/zhbvq21cnf49s43msvbg0rga3f3zigpz-python3.9-pip-22.2.2/lib/python3.9/site-packages/pip/__main__.py", line 31, in <module>
    sys.exit(_main())
  File "/nix/store/zhbvq21cnf49s43msvbg0rga3f3zigpz-python3.9-pip-22.2.2/lib/python3.9/site-packages/pip/_internal/cli/main.py", line 70, in main
    return command.main(cmd_args)
  File "/nix/store/zhbvq21cnf49s43msvbg0rga3f3zigpz-python3.9-pip-22.2.2/lib/python3.9/site-packages/pip/_internal/cli/base_command.py", line 101, in main
    return self._main(args)
  File "/nix/store/zhbvq21cnf49s43msvbg0rga3f3zigpz-python3.9-pip-22.2.2/lib/python3.9/site-packages/pip/_internal/cli/base_command.py", line 223, in _main
    self.handle_pip_version_check(options)
  File "/nix/store/zhbvq21cnf49s43msvbg0rga3f3zigpz-python3.9-pip-22.2.2/lib/python3.9/site-packages/pip/_internal/cli/req_command.py", line 190, in handle_pip_version_check
    pip_self_version_check(session, options)
  File "/nix/store/zhbvq21cnf49s43msvbg0rga3f3zigpz-python3.9-pip-22.2.2/lib/python3.9/site-packages/pip/_internal/self_outdated_check.py", line 236, in pip_self_version_check
    logger.warning("[present-rich] %s", upgrade_prompt)
  File "/nix/store/4h7n4af8z6bqjhisn5xf1h1bljan44yk-python3-3.9.15/lib/python3.9/logging/__init__.py", line 1458, in warning
    self._log(WARNING, msg, args, **kwargs)
  File "/nix/store/4h7n4af8z6bqjhisn5xf1h1bljan44yk-python3-3.9.15/lib/python3.9/logging/__init__.py", line 1589, in _log
    self.handle(record)
  File "/nix/store/4h7n4af8z6bqjhisn5xf1h1bljan44yk-python3-3.9.15/lib/python3.9/logging/__init__.py", line 1599, in handle
    self.callHandlers(record)
  File "/nix/store/4h7n4af8z6bqjhisn5xf1h1bljan44yk-python3-3.9.15/lib/python3.9/logging/__init__.py", line 1661, in callHandlers
    hdlr.handle(record)
  File "/nix/store/4h7n4af8z6bqjhisn5xf1h1bljan44yk-python3-3.9.15/lib/python3.9/logging/__init__.py", line 952, in handle
    self.emit(record)
  File "/nix/store/zhbvq21cnf49s43msvbg0rga3f3zigpz-python3.9-pip-22.2.2/lib/python3.9/site-packages/pip/_internal/utils/logging.py", line 179, in emit
    self.handleError(record)
Message: '[present-rich] %s'
Arguments: (UpgradePrompt(old='22.2.2', new='22.3.1'),)
Finished executing setuptoolsShellHook

For some reason, pip is invoking python3.9 which then tries to invoke it’s own pip which doesn’t exist bc they’re from different packages & python3.9 doesn’t include it’s own pip in it’s bin dir:

[nix-shell:~/code/my-package]$ which python3.9
/nix/store/4h7n4af8z6bqjhisn5xf1h1bljan44yk-python3-3.9.15/bin/python3.9

[nix-shell:~/code/my-package]$ which pip
/nix/store/zhbvq21cnf49s43msvbg0rga3f3zigpz-python3.9-pip-22.2.2/bin/pip

I suspect /nix/store/zhbvq21cnf49s43msvbg0rga3f3zigpz-python3.9-pip-22.2.2/lib/python3.9/site-packages/pip/_internal/utils/entrypoints.py needs to be patched to be a little more nix-aware while finding executables to invoke.

Seems like this error isn’t actually preventing me from using my-package in nix-shell but it is unsightly & doesn’t give a good first impression to teammates who are new to nix. How can I either resolve this problem (w/out needing to PR to nixpkgs ideally) or hide this error?

You’ll want python39.withPackages (ps: with ps; [ pip ]). Basically a python interpreter with pip in its environment.

1 Like

In propagatedBuildInputs? I’m getting the same error with:

  propagatedBuildInputs = [
    (pkgs.python39.withPackages (ps: with ps; [ pip ]))
    pycryptodome
    setuptools
  ];

Should I be using mkShell?

To get a shell with the dependencies accessible by a python interpreter do this:

{ pkgs ? import <nixpkgs> {} }:
let
  inherit (pkgs) python3;
in
pkgs.mkShell {
  packages = [
    (python3.withPackages (ps: with ps; [
      pip
      pycryptodome
      setuptools
    ]))
  ];
}

For when you want to build your application using the shell use something like this:

{ pkgs ? import <nixpkgs> {} }:
let
  inherit (pkgs) python3;

  pve_balance = python3.pkgs.buildPythonApplication {
    pname = "pve_balance";
    version = "0";
    format = "pyproject";

    src = ./.;

    nativeBuildInputs = with python3.pkgs; [
      setuptools
    ];

    propagatedBuildInputs = with python3.pkgs; [
      paramiko
      proxmoxer
      requests
    ];
  };
in
pkgs.mkShell {
  packages = [
    pve_balance
  ];
}
3 Likes

One good example is worth a thousand words. This is beautiful & clarifies several other points of uncertainty I had, thank you very much :grin:

1 Like

Wait one more follow up question: I’m having trouble updating the source code using your second example. Maybe I shouldn’t be using mkShell?

If my python package prints out “hello” and I update it to print “hello world”, I’d like to see that change reflected in the shell immediately without needing to close & reopen the shell. For now, I’m back to using my original shell.nix because it allows a fast tweak/check cycle like:

$ nix-shell <OP shell.nix>
<lots of output including the stack trace mentioned in OP>
[nix-shell] $ my-package
hello
[nix-shell] $ vim file.py # update the string printed
[nix-shell] $ my-package
hello world
[nix-shell]$ which my-project
/tmp/tmp.m0JwP7xpRS/bin/my-project
[nix-shell]$ realpath /tmp/tmp.m0JwP7xpRS/bin/my-project 
/private/tmp/tmp.m0JwP7xpRS/bin/my-project

When I don’t wrap my shell.nix in mkShell then I get my project installed in a private tmp dir which seems to be what enables the live src editing. Is there any way to access a similar private tmp installation while using mkShell?