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 ]))
neovim
firefox
.
.
];
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:
let
qpy-python = (python3.withPackages (ps: with ps; [ qtile pandas numpy ]));
qpy = (pkgs.writeScriptBin "qpy" "#! ${pkgs.bash}/bin/bash\n${qpy-python}/bin/python \"$@\"");
in
{
environment.systemPackages = with pkgs; [
qpy
neovim
firefox
...
];
...
}
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 
(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:
- Use
pkgs.runCommand
instead of pkgs.writeScriptBin
to symlink the said qpy-python’s bin to a new bin file.
- 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!