如何为 crontab 设置 virtualenv?

问题描述 投票:0回答:4

我想设置一个 crontab 来运行 Python 脚本。

假设脚本是这样的:

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

有没有办法为要运行的 Python 脚本指定 virtualenv?在 shell 中我会这样做:

~$ workon myenv

我可以在 crontab 中做一些等效的事情来激活 virtualenv 吗?

python cron virtualenv virtualenvwrapper
4个回答
124
投票

我可以在 crontab 中做一些等效的事情来激活 virtualenv 吗?

这对我来说效果很好...

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

我更喜欢直接从 virtualenv 使用 python ,而不是将 virtualenv

$PATH
硬编码到脚本的 shebang 中...或采购 venv
activate

来自评论

尝试了这个,发现我的脚本无法从同一项目中的其他模块导入。有什么想法为什么会发生这种情况吗?

如果您无法从 cron 运行导入,则可能是目录权限问题,或者您需要 cd 进入导入正常工作的目录。

修改上面的示例:

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

84
投票

如果您使用“workon”,您实际上使用的是“virtualenv 包装器”,它是位于 virtualenv 之上的另一层抽象。 单独的 virtualenv 可以通过 cd'ing 到你的 virtualenv 根目录并运行来激活:

source bin/activate

workon 是 virtualenv 包装器提供的命令,而不是 virtualenv,它执行一些普通 virtualenv 不一定需要的附加操作。 您真正需要做的就是在 virtualenv 根目录中获取 bin/activate 文件来“激活”virtualenv。

您可以设置 crontab 来调用执行此操作的 bash 脚本:

#! /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

10
投票

使用 bash,您可以创建一个通用的虚拟环境包装器,可用于调用 any 命令,就像

time
可以包装任何命令一样。

virt_env_wrapper.bash

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

Bash 的神奇咒语

"$@"
重新转义原始命令行上的所有标记,这样如果您要调用:

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

foo.py
会看到
sys.argv
['bar', 'baz blap']


2
投票

我不确定

workon
,但对于
venv
来说非常简单。唯一要记住的是,
crontab
默认使用
sh
,而不是
bash
,因此您需要使用
.
命令而不是
source

如果您有文件,这里是示例

~/myproject/main.py
:

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

也可以直接调用venv目录下

python
的具体路径,则不需要调用
activate

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

这样做的缺点是您需要指定项目路径两次,这使得维护变得更加棘手。为了避免这种情况,您可以使用 shell 变量,这样您只需指定项目路径一次:

* * * * * project_dir=~/myproject ; $project_dir/.venv/bin/python $project_dir/main.py > /tmp/out3 2>&1
© www.soinside.com 2019 - 2024. All rights reserved.