How to set up environment properly for Python scripts using the "new" flake-based "Nix way"?

Okay, round 3 of me trying to ask an intelligent question about this …

Basically, I’m trying to figure out what the proper “Nix way” is of setting up the environment for Python scripts that use Python modules that won’t work if environment variables (e.g., GI_TYPELIB_PATH) aren’t set correctly, especially if those Python modules are provided via flakes.

I had thought that the correct way to run a Python script in NixOS – especially one that depends on Nix-packaged Python modules – was to either (1) run it with a nix-shell shebang (slow) or (2) package it with a Nix writer (far more performant).

Then I started working with flakes and the new Nix CLI that goes with them, and I noticed that in the new CLI, nix shell (without the hyphen) does not include all the environment variables that nix-shell did, (again, e.g., GI_TYPELIB_PATH), and the Nix writers like writePython3Bin only provide an environment much like that of nix shell, rather than the older nix-shell.

nix develop does seem to provide a full environment, but only for one particular package at a time, and it seems to be squarely designed to provide a development environment for developing that package, not for running scripts.

I then thought that, at least for the case of GI_TYPELIB_PATH, one might patch a Python module in a manner similar to the way GNOME extensions are patched, and tentatively, the derivation for the Python module blivet seemed like an example of just that. However, I found that it still needed GI_TYPELIB_PATH set up to even get its patch to work.

So far, the least bad way of internally patching a Python module seems to be setting entries in the os.environ dictionary-like mapping object, and there do seem to be examples of this in the derivations of GNUCash, uxsim, and steamos-devkit. From my brief attempts at trying it out, it at least seems to be an effective hack.

Does anyone have any ideas better than the last one? Maybe some knowledge of the new Nix tooling that I missed?

I guess I’ll answer my own question. From what I can tell, NixOS has no support for using unpackaged Python scripts outside of a dev shell. Judging from an earlier discussion, on NixOS, one is expected to package just about every script, with the possible exception of some very simple shell scripts. It might let you get away with using an unpackaged Python script, but it’s not a supported use case.

Unfortunately, the tooling for packaging small scripts has what another poster described as “an unpleasant edge case”, where if a Python script relies on a packaged Python module that needs a hook to run (like wrapGAppsHook*), then one’s choices are to manually supply the environment variable value in the makeWrapperArgs argument of the writePython3* Nix-writer that the hook would normally provide or to work with a more complex tool like buildPythonApplication.

Am I about correct?

Yes, that sounds like an accurate summary.

2 Likes

I can’t offer useful commentary, other than I think you are correct, but I am not an expert on nix python packaging when it comes to glib and friends.

META: I just want to say thank you for tugging on this thread, I’ve certainly learnt a few things. I did have a very brief look at workrave in the spirit of helping out but it was dumping core for me and my todo list is a currently a small novel and growing, so I had to tap out.

1 Like