206

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

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

/home/udi/foo有一些必要的子目录,比如/home/udi/foo/logand /home/udi/foo/config,它/home/udi/foo/bar.py指的是。

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

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

编辑:

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

是最紧凑优雅的解决方案。感谢您的回答和解释!

4

4 回答 4

254

这会将您当前的工作目录更改为以便打开相对路径将起作用:

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

但是,您询问了如何更改 Python 脚本所在的目录,即使您在编写脚本时不知道该目录是什么目录。为此,您可以使用以下os.path功能:

import os

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

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

于 2009-09-16T13:26:24.527 回答
54

您可以使用sys.path[0].

os.chdir(sys.path[0])

来自http://docs.python.org/library/sys.html#sys.path

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

于 2012-02-03T14:41:28.983 回答
26

不要这样做。

你的脚本和你的数据不应该混合到一个大目录中。将您的代码放在与您的数据分开的某个已知位置(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 )

不要根据软件的位置“假设”一个目录。从长远来看,它不会很好地工作。

于 2009-09-16T13:34:21.243 回答
23

将您的 crontab 命令更改为

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

(...)启动您的 crond 作为单个命令执行的子 shell 。|| exit 1如果目录不可用,这会导致您的 cronjob 失败。

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

于 2013-01-31T14:37:45.753 回答