Search code examples
pythonenvironment-variablesvirtualenv

How to enable a virtualenv in a systemd service unit?


I want to "activate" a virtualenv in a systemd service file.

I would like to avoid having a shell process between the systemd process and the python interpreter.

My current solution looks like this:

[Unit]
Description=fooservice
After=syslog.target network.target

[Service]
Type=simple
User=fooservice
WorkingDirectory={{ venv_home }}
ExecStart={{ venv_home }}/fooservice --serve-in-foreground
Restart=on-abort
EnvironmentFile=/etc/sysconfig/fooservice.env

[Install]
WantedBy=multi-user.target

/etc/sysconfig/fooservice.env

PATH={{ venv_home }}/bin:/usr/local/bin:/usr/bin:/bin
PYTHONIOENCODING=utf-8
PYTHONPATH={{ venv_home }}/...
VIRTUAL_ENV={{ venv_home }}

But I am having trouble. I get ImportErrors since some entries in sys.path are missing.


Solution

  • The virtualenv is "baked into the Python interpreter in the virtualenv". So for most cases this means you can launch python or console_scripts directly in that virtualenv and don't need to activate the virtualenv first or manage PATH yourself.

    Note: Replace {{ venv_home }} with the venv home dir to use:

    ExecStart={{ venv_home }}/bin/fooservice --serve-in-foreground
    

    or

    ExecStart={{ venv_home }}/bin/python {{ venv_home }}/fooservice.py --serve-in-foreground
    

    and remove the EnvironmentFile entry.

    To verify that it is indeed correct you can check sys.path by running

    {{ venv_home }}/bin/python -m site
    

    and comparing the output to

    python -m site