0

I'm trying to daemonise a python script using systemd, but constantly get the error "No module named 'oandapyV20'" after activating the daemon.

The script is at location: /home/user/workingdir/script.py

The virtual environment is at: /home/user/venv/bin/

My best guess at how to build the service from docs I've found is as follows:

[Unit]
Description=DataLoader
[Service]
User=root
Group=root
WorkingDirectory=/home/user/workingdir
ExecStart=/home/user/venv/bin/python3 script.py
[Install]
WantedBy=multi-user.target

What does work...

python3 script.py

or activating virutal environment

source /home/user/venv/bin/activate; python3 script.py

Although that works outside of the service, nothing I've tried works when calling from systemd.

Where am I going wrong? What am I not realising?

Eventual solution (with little understanding)

[Unit]
Description=DataLoader
[Service]
User={user_name}
Group={user_name}
WorkingDirectory=/home/{user_name}/workingdir
ExecStart=/usr/bin/python3 script.py
Restart=always
[Install]
WantedBy=multi-user.target
7
  • What happens if you become root with sudo su - (with hyphen) and execute cd /home/user/workingdir; /home/user/venv/bin/python3 script.py? Is it different with sudo su (no hyphen)? If so, I'd scrutinize differences in environment variables. You might also run source /home/user/venv/bin/activate; which python3 to make sure you're actually calling /home/user/venv/bin/python3 as you currently believe.
    – gnubeard
    Apr 1, 2020 at 20:56
  • @gnubeard thanks for your comment. After logging in as route cd /home/user/workingdir; /home/user/venv/bin/python3 script.py fails with the same module not recognised error. I installed the module whilst logged in as root, but it still fails with same error. I'm missing some fundamental concept about linux or python, why would the module not be available when root? What should I read up on? I'll work on the rest of your suggestions next.
    – goose
    Apr 1, 2020 at 21:14
  • That indicates that there's something different between your environment and root's environment. Use the env command to print all environment variables, and use source /home/user/venv/bin/activate; which python3 to ensure the python3 you're calling is the python3 you think you're calling. If it's calling a different python3, I'd especially inspect differences in $PATH.
    – gnubeard
    Apr 1, 2020 at 21:26
  • @gnubeard /home/user/venv/bin/activate; which python3 outputs /usr/bin/python3, don't yet understand why it's not using the virtual evironment.
    – goose
    Apr 2, 2020 at 11:56
  • That means that when you call source /home/user/venv/bin/activate, it's not setting your $PATH or ($PYTHONPATH) (at least not to what you had thought.) Hopefully that goes a long way toward explaining the discrepancy.
    – gnubeard
    Apr 2, 2020 at 12:25

1 Answer 1

2

It appears that you have been operating under the assumption that whenever you called source /home/user/venv/activate, the python3 command (and the pip3 command) would subsequently call the relevant executable from /home/user/venv/bin.

However, the clarification you added in the comments indicates that assumption was incorrect. You hadn't been calling the python from your virtual environment when running script.py; you had been calling the python in /usr/bin (and its corresponding pip too, it seems, since the python in your virtualenv doesn't seem to have the oandapyV20 module installed, while the system python does.)

Examine the output of

echo $PATH
echo $PYTHONPATH

The $PATH environment variable is a colon-separated list of paths on your system to be searched when you enter a command. Either /home/user/venv/bin is not present in that list or it occurs after an occurrence of /usr/bin, which contains a match for python3 ($PATH will stop being scanned after the first match.) $PATH is usually set by $HOME/.bashrc (or /etc/bashrc if not set there) and if your assumption had been correct, /home/user/venv/activate would have been setting $PATH to prepend /home/user/venv/bin to it.

$PYTHONPATH should tell python where to look for modules to load. (It can also be modified or read from your script with sys.path.)

That explains why changing your systemd unit's command worked-- it's finally calling the same python that your working command did.

1
  • Thanks gnubeard, I really appreciated the help. This one's taken some time to get to the bottom of. I'm really keen on understanding linux more, but can't really see where to start. Pls feel free to recommend any good resources that helped you learn it.
    – goose
    Apr 2, 2020 at 13:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .