我每分钟从crontab运行一个python shell:

* * * * * /home/udi/foo/bar.py

/home/ uddi /foo有一些必要的子目录,如/home/ uddi /foo/log和/home/ uddi /foo/config,其中/home/ uddi /foo/bar.py指的是这些子目录。

问题是crontab从不同的工作目录运行脚本,因此试图打开./log/bar.log失败。

是否有一种好方法告诉脚本将工作目录更改为脚本自己的目录?我想有一种解决方案可以适用于任何脚本位置,而不是显式地告诉脚本它在哪里。

编辑:

os.chdir(os.path.dirname(sys.argv[0]))

是最简洁优雅的解决方案。谢谢你的回答和解释!


当前回答

不要这样做。

你的脚本和数据不应该被放在一个大目录中。将代码放在与数据分离的已知位置(site-packages或/var/opt/udi或其他)。在代码上使用良好的版本控制,以确保当前版本和以前的版本彼此分离,以便您可以返回到以前的版本并测试未来的版本。

底线:不要混淆代码和数据。

数据是宝贵的。代码来来去去。

提供工作目录作为命令行参数值。您可以提供一个默认的环境变量。不要推断(或猜测)

让它成为一个必需的参数值,然后这样做。

import sys
import os
working= os.environ.get("WORKING_DIRECTORY","/some/default")
if len(sys.argv) > 1: working = sys.argv[1]
os.chdir( working )

不要根据软件的位置“假定”一个目录。从长远来看,这不会有好结果。

其他回答

将crontab命令更改为

* * * * * (cd /home/udi/foo/ || exit 1; ./bar.py)

(…)启动一个子shell,您的crond将其作为单个命令执行。|| exit 1会导致cronjob在目录不可用时失败。

尽管从长远来看,对于特定的脚本,其他解决方案可能更加优雅,但在无法修改想要执行的程序或命令的情况下,我的示例仍然很有用。

您可以使用sys.path[0]来获得一个更短的版本。

os.chdir(sys.path[0])

从http://docs.python.org/library/sys.html sys.path

在程序启动时初始化,这个列表的第一项, 路径[0],是包含脚本的目录 调用Python解释器

不要这样做。

你的脚本和数据不应该被放在一个大目录中。将代码放在与数据分离的已知位置(site-packages或/var/opt/udi或其他)。在代码上使用良好的版本控制,以确保当前版本和以前的版本彼此分离,以便您可以返回到以前的版本并测试未来的版本。

底线:不要混淆代码和数据。

数据是宝贵的。代码来来去去。

提供工作目录作为命令行参数值。您可以提供一个默认的环境变量。不要推断(或猜测)

让它成为一个必需的参数值,然后这样做。

import sys
import os
working= os.environ.get("WORKING_DIRECTORY","/some/default")
if len(sys.argv) > 1: working = sys.argv[1]
os.chdir( working )

不要根据软件的位置“假定”一个目录。从长远来看,这不会有好结果。

这将改变您当前的工作目录,以便打开相对路径将工作:

import os
os.chdir("/home/udi/foo")

但是,您询问了如何更改到Python脚本所在的目录,即使您在编写脚本时不知道该目录是什么。要做到这一点,您可以使用os。路径功能:

import os

abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
os.chdir(dname)

这将获取脚本的文件名,将其转换为绝对路径,然后提取该路径的目录,然后更改到该目录。