Michael Maclean

Developing with Flask on NixOS

I recently acquired a second hand ThinkPad to run NixOS on, and I’ve been using it recently to mess around with a couple of small web projects. I’m prototyping one of these in Flask, and have been using NixOS’s own Flask package in order to do so.

I found that I could quite happily do flask run, but as soon as I tried to enable development mode, I’d end up with an error like this:

$ FLASK_APP=myapp FLASK_ENV=development flask run
 * Serving Flask app "myapp" (lazy loading)
 * Environment: development
 * Debug mode: on
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
  File "/nix/store/dpdfxfjf6azdgnka78fhsch3a8y3d46g-python3.7-Flask-1.0.2/bin/flask", line 2
    export PATH='/nix/store/96p42644i76jqgdkxjgyl3f0c8n8k16j-python3-3.7.4/bin:/nix/store/dpdfxfjf6azdgnka78fhsch3a8y3d46g-python3.7-Flask-1.0.2/bin:/nix/store/dvzig77cx97rdxn5i2pdmyblm8f6pf7d-python3.7-setuptools-40.8.0/bin'${PATH:+':'}$PATH
              ^
SyntaxError: invalid syntax

This looks a bit like something is attempting to run a Bash script through the Python interpreter. I didn’t understand why this was happening until I encountered this issue on Nix’s github which suggests that it ought to be fixed upstream, but that it might be possible to override it in Nix. The code given there to do so didn’t neatly copy and paste into shell.nix as I had hoped, but after some tinkering I got it to work. Here’s what I ended up with:

with import <nixpkgs> {};

let
myWerkzeug = python37Packages.werkzeug.overrideAttrs (oldAttrs: rec {
  postPatch = ''
    substituteInPlace werkzeug/_reloader.py \
      --replace "rv = [sys.executable]" "return sys.argv"
  '';
  doCheck = false;
});

myFlask = python37Packages.flask.override ({ werkzeug = myWerkzeug; });

in mkShell {
  buildInputs = [
    python37
    myFlask
  ];
}

Probably not hard to anyone who properly understands Nix, but I learned a couple of things doing it. Hopefully someone else will find this useful.