'How to set virtualenv for a crontab?

I want to set up a crontab to run a Python script.

Say the script is something like:

#!/usr/bin/python
print "hello world"

Is there a way I could specify a virtualenv for that Python script to run in? In shell I'd just do:

~$ workon myenv

Is there something equivalent I could do in crontab to activate a virtualenv?



Solution 1:[1]

Is there something equivalent I could do in crontab to activate a virtualenv?

This works well for me...

## call virtualenv python from crontab
0    9    *    *    *    /path/to/virtenv/bin/python /path/to/your_cron_script.py

I prefer using python directly from the virtualenv instead of hard-coding the virtualenv $PATH into the script's shebang... or sourcing the venv activate

Solution 2:[2]

With bash, you can create a generic virtual env wrapper that you can use to invoke any command, much like how time can wrapper any command.

virt_env_wrapper.bash:

#!/bin/bash    
source path/to/virtual/env/bin/activate
"$@"

Bash's magical incantation "$@" re-escapes all tokens on the original command line so that if you were to invoke:

virt_env_wrapper.bash python foo.py bar 'baz blap'

foo.py would see a sys.argv of ['bar', 'baz blap']

Solution 3:[3]

I'm not sure about workon, but it's pretty straightforward for venv. The only thing to remember is that crontab uses sh by default, not bash, so you need to use the . command instead of source.

Here are examples if you have a file ~/myproject/main.py:

* * * * * cd ~/myproject && . .venv/bin/activate && python main.py > /tmp/out1 2>&1

You could also directly call the specific path of the python in the venv directory, then you don't need to call activate.

* * * * * ~/myproject/.venv/bin/python ~/myproject/main.py > /tmp/out2 2>&1

The downside of that is you would need to specify the project path twice, which makes maintenance trickier. To avoid that, you could use a shell variable so you only specify the project path once:

* * * * * project_dir=~/myproject ; $project_dir/.venv/bin/python $project_dir/main.py > /tmp/out3 2>&1

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 wisbucky