2

I have a systemd service that regularly reads the first line of a root-owned file, transforms it and then uses png_util:

import png_util

with open('root-owned-file', 'r') as f:
  f.read()

...rest of logic...

Now, when the systemd daemon starts, it doesn't have access to the png_util library I installed with pip (pip install png_util) because that only installs it for the installing user. This also happens, when I start the script with sudo:

ModuleNotFoundError: No module named 'png_util'

If I read a file owned by me and execute the script normally as my user, everything works fine.

The systemd service:

[Unit]
Description=PNG

[Service]
ExecStart=/tmp/pngreader

[Install]
WantedBy=multi-user.target

Is the trick simply using pip install --user root and then setting the PYTHONPATH for the root user somehow?

JJ Abrams
  • 365
  • 2
  • 11

1 Answers1

4

I think you can get what you need with a virtual environment.

You need to create a virtual environment specifically for that script. You will install all the packages you will need for it with the right versions in that environment. As long as you run your script with that virtual environment active everything will be available.- See the venv documenttion here

To create a virtual environment you run python3 -m venv <your_venv_path> with path being where you want to store it, e.g. ~/.venvs/my_project/

To install packages you first have to make it active and then run pip

source <your_venv_path>/bin/activate
pip install png_util

To here you would have your virtual environment ready and your package installed. If you run your script with your virtual environment active the package will be available.

Now, because your script is a daemon this is how you make sure it runs within your virtual environment. Basically the virtual environment creates a copy of Python in and you just add to your script the instruction to use that "copy" of python. You do it by just adding #!<your_venv_path>/bin/python as the first line of your script.

That way when your script runs it does run within that virtual environment where all the packages are installed.

PS: Potentially everything could work by simply running pip as sudo because it will install the package system wide making it available for all users. But that option is highly discouraged for the security risks it creates, see this post with security risks of running sudo pip

Hope this helps!!

Alvaro Aguilar
  • 694
  • 8
  • 23
  • I wasn't aware of virtual environments, but that really worked. Thanks a bunch for the detailed description!! – JJ Abrams Feb 23 '20 at 12:44
  • 1
    Glad it was useful. Virtual environments are great and it is best to use them for all your projects. The main benefit is that you have all the packages you need for a project, only the ones you need and the right versions in the environment where you run that project. Then if a different project requires different versions nothing would get mixed up because each runs on its own venv. I would definitely research this and start using it all the time. Google `pip freeze > requirements.txt` to see how it is used. – Alvaro Aguilar Feb 23 '20 at 13:47