Python 脚本未在 crontab 中运行调用 pysaunter

Posted

技术标签:

【中文标题】Python 脚本未在 crontab 中运行调用 pysaunter【英文标题】:Python Script not running in crontab calling pysaunter 【发布时间】:2013-07-09 02:39:40 【问题描述】:

我阅读了多篇文章和许多文章,详细说明了 cron 作业中的 scipts 需要保留在脚本本身内运行所需的环境变量,因为在 cron 中打开了 shell。我的情况是独一无二的,因为我的路径变量都是按照讨论的那样设置的,这反过来又会使用subprocess.call() 成功调用 pysaunter python egg,但它似乎从那里崩溃了。这会导致整个过程中断一个 cron 作业。

为清楚起见,以下是我参考的步骤:

1) cronjob calls run_test.py -n foo
2) run_test.py sets the environment variables correctly 
(cur_shell_path=sys.path (converted to proper path string, not shown here)
 my_env= os.environ.copy()
 my_env["PATH"] = my_env["PATH"] + cur_shell_path)
3) run_test.py calls subprocess.call("pysaunter -m foo -v", env=my_env, shell=True)

第 3 步的输出显示它正在找到 egg 并成功开始从 pysaunter 加载必要的模块,但是在尝试查找用于修改 pysaunter 的目录时它会中断。错误显示:

ImportError: no module named helpers

我多次尝试将此路径添加到环境中,但似乎从未找到包含 helpers.py 的目录。从交互式 shell 调用命令 pysaunter -m foo -v 可以正常工作。

我在 pysaunter 上找不到太多帮助,所以我认为这里不需要过多的 pysaunter 细节。但是,如果您对 pysaunter 有更多了解,请告诉我您是否需要更多信息。我不确定要分享什么。

我还阅读了许多帖子,讨论了通过编辑 .profile/.bash_profile 来更改 shell 的默认行为的能力。我试图找到一个可以让我的路径变量全局可访问的地方,但我找不到任何东西。我不确定这是如何完成的,它可能会解决我的问题,所以如果您对此有所了解,请告诉我。

最后说明,这是在 Mac 10.7.5 上运行的。

【问题讨论】:

【参考方案1】:

经过多次试验和错误,以及许多 ***.com 文章和其他在线教程,在 Perl 脚本的帮助下,我发现做了类似的事情,我能够弄清楚需要做什么才能获得这工作。

以下是确保一切设置正确的步骤:

    1234563测试你的脚本以确保它有效。

    编辑您的 crontab 以包含运行您的 cron 作业中的脚本(找到 here 和 here)。

    a) 确保在 PATH 变量 (.) 中包含根目录,如 here 所述。基本上,如果您使用命令运行可执行文件,它需要能够找到根目录或存储可执行文件的目录,还可能是这些:(/sbin:/bin:/usr/sbin:/usr/bin)。

    在您的 crontab 文件中,创建一个 cronjob,它将当前目录更改为您之前成功运行脚本的目录(例如,/Users/user/Documents/foo)。

    a) 这将如下所示:

    * * * * cd /Users/user/Documents/foo; bar -l doSomething -v 
    

    由于我的问题专门针对调用可执行文件,因此有必要注意有多种方法可以编写 Python 脚本以运行(尽管在发现过程中我了解到这适用于使用 cron 中的子进程进行的任何调用)。

    第一种方法如下:

    ... #some script calls
    my_env = os.environ.copy()
    my_env["PYTHONPATH"] = ":".format(os.environ["PATH"] ,"<path you want to include>")
    os.chdir("<path/to/desired/directory>")
    subprocess.Popen(<call_as_string>, env=my_env, shell=True)
    

    第二个看起来像这样:

    ... #some script calls
    os.environ["PYTHONPATH"] = ":".format(os.environ["PATH"] ,"<path you want to include>")
    os.chdir("<path/to/desired/directory>")
    subprocess.Popen(<call_as_list_of_arguments)
    

    由于可执行文件需要包含在调用它的 shell 中的 helpers 目录的路径,因此有必要将环境变量传递给可执行文件,如 here 所述。不过,我发现修改环境中的 PATH 变量不适用于 cron 作业,但设置 PYTHONPATH 可以。我读到here,shell 使用 PATH 变量仅查找可执行文件,因此对于 cronjob 中的新 shell,您需要向 shell 传递 PYTHONPATH 以查找新的 Python 模块。 (这也是explained in the Python docs。)

    问题中引用的子流程文档中解释了这两种不同方法之间的区别,但可以在here 找到有关此模块的良好教程。

【讨论】:

【参考方案2】:

你说的没有道理。

你说shell_env = sys.pathsys.path 是 python 查找模块的文件夹列表,而不是环境变量映射!

然后你在subprocess.call 中使用它。也许你的意思是写env=my_env

这是下一个问题。首先,PATH 应该是由':' 分隔的文件夹列表。您只需将 shell_path 添加到最后一个文件夹即可。

最后,python 使用PYTHONPATH 作为列表来定位 python 模块(这似乎是你遇到的问题。)

【讨论】:

感谢您指出我的问题,我现在已修复它以显示 my_env 正在通过。此外,在基于 Unix 的机器上,冒号 (:) 用于分隔路径值,因此这不是问题。最后,Pythonpath 用于搜索本地目录,在 Unix 上,本地目录由 shell 所在的launched 定义。由于 cron 作业调用的非交互式 shell 不是从正确的目录启动并且不读取 .profile 或 .bash_profile,因此没有添加路径,因此没有设置 Pythonpath。 您对冒号的看法是正确的。我修好了。您需要在 cron 作业中设置 PYTHONPATH。您可以创建一个包装脚本,将 PYTHONPATH 设置为所需的目录,然后调用 python 脚本。

以上是关于Python 脚本未在 crontab 中运行调用 pysaunter的主要内容,如果未能解决你的问题,请参考以下文章

[Shell]crontab 运行任务调用shell脚本,相对路径无法找到

如何使用 crontab 运行运行 Python 脚本的 Bash 脚本

尽管脚本在手动运行时有效,但 Crontab 没有在 macOS 中运行我的 python 脚本

关于linux系统下CRONTAB运行python脚本不生效

Crontab定时任务中python3脚本无法运行问题解决

实现crontab定时调用python脚本,以及command not found的问题