【问题标题】:How to set virtualenv for a crontab?如何为 crontab 设置 virtualenv?
【发布时间】:2011-05-08 05:33:50
【问题描述】:

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

假设脚本是这样的:

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

有没有办法可以为该 Python 脚本指定一个 virtualenv 来运行?在 shell 中我会这样做:

~$ workon myenv

我可以在 crontab 中做些什么来激活 virtualenv 吗?

【问题讨论】:

    标签: python cron virtualenv virtualenvwrapper


    【解决方案1】:

    我不确定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
    

    【讨论】:

      【解决方案2】:

      使用 bash,您可以创建一个通用的虚拟 env 包装器,您可以使用它来调用 任何 命令,就像 time 可以包装任何命令一样。 p>

      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']

      【讨论】:

        【解决方案3】:

        另一个适合我的解决方案...

        0    9    *    *    *    /path/to/virtenv/bin/python /path/to/cron_script.py
        

        我更喜欢直接从 virtualenv 中使用 python...

        【讨论】:

        • 这很好用。事实上,也可以将python解释器的绝对路径放在脚本本身的shebang(又名#!)中,当然,使脚本可执行。
        • @AvinashMeetoo 是的,这是可能的,但这样它就变成了位置和设置依赖
        • 试过这个,发现我的脚本无法从同一个项目的其他模块导入。任何想法为什么会发生这种情况?
        • @NathanGould 您可能需要在您的虚拟环境virtual_env_folder/lib/python3.3/site-packages/app_name.pth 中添加一个.pth 文件,其中包含此处指示的应用程序位置stackoverflow.com/a/10739838/1082673
        • 这是更好的解决方案
        【解决方案4】:

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

        source bin/activate
        

        workon 是由 virtualenv wrapper 提供的命令,而不是 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
        

        【讨论】:

        • 我还需要使用“#!/usr/bin/python”在我的脚本中指定我的 Python 解释器吗?但我的 virtualenv 可能指向不同的解释器。这就是我感到困惑的地方。
        • 你可能想看看 bin/activate 在做什么。激活 virtualenv 基本上只是修改您的 PATH env var 以指向特定版本的命令,例如 python 等。如果您激活 virtualenv,然后尝试运行 /usr/bin/python,您可能使用也可能不使用该版本您的 virtualenv 所期望的 python。而不是执行“#!/usr/bin/python”,您可以执行“#!/usr/bin/env python”,让 env 根据您的 PATH 决定运行哪个 python。
        • 确保 #! /bin/bash 也是文件的第一行,前面没有空格
        • 并非所有工作都只是获取 bin/activate 文件。 Virtualenvwrapper 也有你可以使用的钩子(例如 postactivate),如果你只是获取激活文件,它将不会运行。
        猜你喜欢
        • 1970-01-01
        • 2012-04-08
        • 2017-12-30
        • 2011-06-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-13
        相关资源
        最近更新 更多