Qtile package overwrites my global python environment

Hello, I’m a long time linux user but a newbie nixos explorer. For the last few days I’ve been learning about nix and configuring my nixos installation. I’m using qtile as my windows manager, which is written and configured purely in python. But I noticed something strange. When I’m in qtile, I can’t access any of the python packages I defined in my configuration.nix file. I defined the python packages like this:

environment.systemPackages = with pkgs; [
  (python3.withPackages (ps: with ps; [ qtile pandas numpy ]))

I can’t import any of them in my scripts. I know the more appropriate nix way of doing this, is using my scripts like this:

#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p "python3.withPackages(ps: [ ps.qtile ])"

This works but simplest scripts take more than a second to execute. It makes some of my scripts, like the one I use to increase/decrease my volume by 2%, unusable.

I found this discussion: Using Qtile changes Python environment and seems like the problem is solved by a commit mentioned there.

I’m on 23.05 stable channel and I’m having the exact problem. Is there at least a hacky way to solve this issue?

Any help would be much appreciated, thanks.

nix-shell is meant to create an ephemeral development environment, you will eventually want to change the shebang to a specific python (see my code below). You may want to continue using nix-shell if you haven’t concluded which python packages your script will require yet.

But once you’re certain about the python packages it requires (say qtile pandas numpy and nothing else), you can “rename” the python above before adding it to global system packages. Here’s how I would do it:

qpy-python = (python3.withPackages (ps: with ps; [ qtile pandas numpy ]));
qpy = (pkgs.writeScriptBin "qpy" "#! ${pkgs.bash}/bin/bash\n${qpy-python}/bin/python \"$@\"");
environment.systemPackages = with pkgs; [

after switching to the new configuration.nix, you’ll have a command qpy in your PATH that is effectively just python with qtile pandas numpy included. You can run it with no argument to open the python repl, or passing a .py file name to run a script.

I use this approach to create multiple versions of python is my system with different names for scripts with different python dependencies. I don’t even have any python (the original name) in my PATH :slight_smile:

(btw, such customization should better be placed in an overlay, but ignore that for now).

1 Like

That’s so cool, thanks for the answer! Since we are creating the environment during nixos-rebuild, it works instantly without bumping up my scripts’ start up time.

But instead of creating a bash script and adding it to the PATH, can I directly add ${qpy-python}/bin/python to PATH?
Like creating a symbolic link from ${qpy-python}/bin/python to /run/current-system/sw/bin/qpy

you already did that with your original code, I just extracted it to a let. The problem is just you don’t know which python is your PATH is which.

The problem is just you don’t know which python is your PATH is which.

Not as python but with a different name like qpy. I can create a symbolic link from ${qpy-python}/bin/python to /run/current-system/sw/bin/qpy myself but I every time a dependency updates in qpy-python env, the folder name will change and I have to redo the linking. Is there a way to do that in configuration.nix so I don’t have to do it myself?

ah, I guess I misunderstood your previous message.

You should avoid directly manipulating your system that way. Instead, just change the .nix file. Instead of creating a bash script like I did, I can think of two more ways:

  1. Use pkgs.runCommand instead of pkgs.writeScriptBin to symlink the said qpy-python’s bin to a new bin file.
  2. Adding qpy-python’s bin to PATH environment via environment.variables though I wouldn’t recommend doing that especially when you’re still new to nix. I only mention this approach to demonstrate the nix way in contrast to direct manipulation.

You can look up #1 and try to implement yourself.

Here’s the answer:

       (pkgs.runCommand "qpy" {}
         mkdir -p $out/bin
         ln -s ${qpy-python}/bin/python $out/bin/qpy
1 Like

That’s exactly what I need, thank you so much for your help!