Python脚本没有在调用pysaunter的crontab中运行

时间:2013-07-11 00:06:17

标签: python shell cron crontab cron-task

我已阅读多篇帖子和许多文章,详细说明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上运行。

2 个答案:

答案 0 :(得分:3)

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

以下是确保正确设置所有内容的步骤:

  1. 确保您在PYTHONPATH中找到所需的变量(找到herehere,并获取更多信息。转到here).profile或.bash_profile对于您要测试脚本的任何shell,以确保它有效。

  2. 编辑您的crontab以包含运行您的目录所需的目录 cron作业中的脚本(找到herehere)。

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

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

    a)这将如下所示:

    * * * * cd /Users/user/Documents/foo; bar -l doSomething -v 
    
  4. 由于我的问题专门涉及调用可执行文件,因此有必要注意有多种方法可以编写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,你需要传递一个PYTHONPATH来查找新的Python模块。 (这也是explained in the Python docs。)

    在问题中引用的子流程文档中解释了两种不同方法之间的差异,但可以找到关于此模块的一个很好的教程here

答案 1 :(得分:1)

你所说的话毫无意义。

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

然后在subprocess.call中使用它。也许你打算写env=my_env

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

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