【问题标题】:Cron job does not load virtualenv env var for working with django.setup()Cron 作业不会加载 virtualenv env var 以使用 django.setup()
【发布时间】:2017-08-26 16:44:38
【问题描述】:

嗯,我有一个像这样的项目结构:

my_project
   |-scripts
   |  |- my_script.py
   |
   |-django_project
      |- myApp
      |  |- models.py
      |  |- ...
      |- django_project
         |- settings.py
         |- ...

我在 virtualenv 中运行 Django,在 my_script.py 中我必须使用一些 myApp.models

所以,我是这样做的:

my_script.py

#!/usr/bin/env python
import django
django.setup()

from myApp.models import foo

# do things

由于我在 virtualenv 中,为了使 django.setup() 正常工作,我在我的 virtualenv ($VIRTUAL_ENV/bin/postactivate) 中设置:

export DJANGO_SETTINGS_MODULE = django_project.settings

我在路径中添加了django_project

$ workon my_virtualenv
$ python -c "import sys; print sys.path" 
['', '/my_project/django_project', ...]

仅此而已。

如果我激活我的 virtualenv 然后我运行 my_script.py 一切正常。

但如果我安排类似的cron 工作:

00 00 * * * /.../.virtualenvs/my_virtualenv/bin/python /.../my_project/scripts/my_script.py >> /.../test/test.log 2>&1

我得到这个错误:

django.core.exceptions.ImproperlyConfigured:请求的设置 LOGGING_CONFIG,但未配置设置。你必须要么 定义环境变量 DJANGO_SETTINGS_MODULE 或调用 settings.configure() 在访问设置之前。

似乎my_virtualenv 激活设置未正确加载。

为什么会发生这种情况,我该如何解决?

【问题讨论】:

  • 删除你的 django.setup() 调用。如果您正在使用/设置 DJANGO_SETTINGS_MODULE,它应该在那里找到您的所有设置。
  • @thebjorn 根据 Django 文档,您必须修复 env 变量并调用 django.setup()。我试过你的提示,但没有用

标签: python django cron virtualenv crontab


【解决方案1】:

在你的 python 文件上试试这个:

import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_project.settings")
import django
django.setup()

我建议您将my_scriptfile 定位到manage.pyfile 所在的项目根目录中。

如果不工作,试试这样:

import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_project.django_project.settings")
import django
django.setup()

【讨论】:

  • +1 '因为第一个解决方案运行良好。但是我仍然不明白为什么在作业开始时我的 env var 没有被 cron 设置。我想可能没有真正的虚拟环境激活事件。
【解决方案2】:

我们使用一个小的shell脚本来激活virtualenv:

$ cat run-python.sh
#!/bin/bash

# put run-python.sh's directory on path (probably not needed, we call
# auxiliary scripts in the same directory)
myname="$0"
binprefix="$(dirname ${myname})"
export PATH=${binprefix}:${PATH}

VENV_DIR = '/path/to/venv/root'

# activate virtualenv
pushd ${VENV_DIR} > /dev/null
. bin/activate
popd > /dev/null

# set DJANGO_SETTINGS_MODULE
if [ "x$DJANGO_SETTINGS_MODULE" == "x" ]; then
  export DJANGO_SETTINGS_MODULE="default.settings"
else
  export DJANGO_SETTINGS_MODULE
fi

exec python $@

并在 crontab 中使用它,例如:

0/15 * * * *    DJANGO_SETTINGS_MODULE=myapp.settings run-python.sh /path/to/python/script.py

【讨论】:

  • 是的,好主意!关于不通过 cron 触发标准钩子的原因有什么想法吗?
  • 可能是因为 cron 没有“任何”环境。您需要明确设置要使用的任何内容。此外,由于您没有运行activate,我猜想也不会运行任何后激活脚本(只需在 virtualenv 中调用python 可执行文件,当您进入 Python 时,大多数事情都会正确完成,并且会正常工作不过在很多情况下都很棒)
【解决方案3】:

问题在于 cron 不是交互式 shell,因此您的 .bash_profile 和 .bashrc 都不是它的来源。

因此,您无需获取脚本 virtualenvwrapper.sh,该脚本定义了 workon 命令以及钩子的工作方式。

要解决这个问题,您可以直接在 crontab 中定义您需要的一组变量,即

WORKON_HOME= the same as in your .bash_profile
PROJECT_HOME= the same as in your .bash_profile
VIRTUALENVWRAPPER_SCRIPT= the same as the value of the variable VIRTUALENVWRAPPER_SCRIPT in interactive shell (usually /usr/local/bin/virtualenvwrapper.sh)

然后添加

source ${VIRTUALENVWRAPPER_SCRIPT}

在您计划的所有脚本的开头(如果您希望它们使用 virtualenvwrapper)

【讨论】:

    猜你喜欢
    • 2021-12-21
    • 2019-10-01
    • 1970-01-01
    • 2012-11-07
    • 2014-01-24
    • 2018-04-03
    • 2014-08-26
    • 2011-08-15
    • 1970-01-01
    相关资源
    最近更新 更多