How to set virtualenv for a crontab?

PythonCronVirtualenvVirtualenvwrapper

Python Problem Overview


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?

Python Solutions


Solution 1 - Python

> 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 - Python

If you're using "workon" you're actually using "virtualenv wrapper" which is another layer of abstraction that sits on top of virtualenv. virtualenv alone can be activated by cd'ing to your virtualenv root directory and running:

source bin/activate

workon is a command provided by virtualenv wrapper, not virtualenv, and it does some additional stuff that is not necessarily required for plain virtualenv. All you really need to do is source the bin/activate file in your virtualenv root directory to "activate" a virtualenv.

You can setup your crontab to invoke a bash script which does this:

#! /bin/bash    
cd my/virtual/env/root/dir
source bin/activate

# virtualenv is now active, which means your PATH has been modified.
# Don't try to run python from /usr/bin/python, just run "python" and
# let the PATH figure out which version to run (based on what your
# virtualenv has configured).

python myScript.py

Solution 3 - Python

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 4 - Python

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionContinuationView Question on Stackoverflow
Solution 1 - PythonMike PenningtonView Answer on Stackoverflow
Solution 2 - PythonAndy WhiteView Answer on Stackoverflow
Solution 3 - PythonRoss RogersView Answer on Stackoverflow
Solution 4 - PythonwisbuckyView Answer on Stackoverflow