azalea says

Adventures of a space in path

Two names were proposed for a path, and I—
I chose the one with a space,
And that has made all the difference.
        -- in tribute to Robert Frost

On Ubuntu, I put my django + celery + virtualenv project in a path with a space, just being consistent with the Windows counterpart. It tured out to be a total adventure for me.

First, all the scripts in the virtual environment cannot be run.

Shell complains:

zsh: ./pip: bad interpreter: "/opt/broken_path_preceding_a_space: no such file or directory"

This is a known issue of virtualenv, because space in shebang line of *nix system is interpreted as separate arguments.

So I fixed shebang line by:

sudo sed -i '1 s|^.*$|#!/usr/bin/env python|' "$INSTDIR/venv/bin/celery"

where $INSTDIR is the path with space where virtual environment venv is installed, and the sed command just replaces the first line with #!/usr/bin/env python. This works because activate script prepends $VIRTUAL_ENV to $PATH.

However, it does not work if running the scripts with sudo:

> $INSTDIR/venv/bin/activate
(venv)
> which python
> $INSTDIR/venv/bin/python
> sudo which python
> /usr/bin/python

Because activating venv only modifies the current user’s $PATH. i.e.:

> env | grep ^PATH
PATH=$INSTDIR/venv/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/sbin:/bin
> sudo env | grep ^PATH
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/sbin:/bin

See also this.

Although it is fine to call the script with $INSTDIR/venv/bin/python -m pip, running celeryd requires sudo:

sudo /etc/init.d/celeryd 

which cannot find python packages installed in the virtual environment.

Solution:

sudo env "PATH=$PATH" /etc/init.d/celeryd

Possible alternative:

Use supervisor.

Or keep calm and remove the space…

ubuntu virtualenv celery · Tweet Edit