问题:python:将脚本工作目录更改为脚本自己的目录
我每分钟从crontab运行python shell:
* * * * * /home/udi/foo/bar.py
/home/udi/foo
有一些必要的子目录,例如/home/udi/foo/log
和/home/udi/foo/config
,它/home/udi/foo/bar.py
指的是。
问题是crontab
从另一个工作目录运行脚本,因此尝试打开./log/bar.log
失败。
有没有办法告诉脚本将工作目录更改为脚本自己的目录?我想找到一种适用于任何脚本位置的解决方案,而不是明确告诉脚本位置。
编辑:
os.chdir(os.path.dirname(sys.argv[0]))
是最紧凑的优雅解决方案。感谢您的回答和解释!
回答 0
这会将当前工作目录更改为,以便打开相对路径将起作用:
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)
这将获取脚本的文件名,将其转换为绝对路径,然后提取该路径的目录,然后更改为该目录。
回答 1
您可以使用来获得较短的版本sys.path[0]
。
os.chdir(sys.path[0])
来自http://docs.python.org/library/sys.html#sys.path
在程序启动时进行初始化,该列表的第一项
path[0]
是包含用于调用Python解释器的脚本的目录。
回答 2
不要这样
您的脚本和数据不应混入一个大目录中。把你的代码在一些已知的位置(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 )
不要根据软件的位置“假定”目录。从长远来看,它将无法很好地工作。
回答 3
将您的crontab命令更改为
* * * * * (cd /home/udi/foo/ || exit 1; ./bar.py)
在(...)
您的crond执行作为一个单一的命令启动一个子shell。如果|| exit 1
目录不可用,则导致您的cronjob失败。
尽管从长远来看,其他解决方案对于您的特定脚本可能更优雅,但是在您无法修改要执行的程序或命令的情况下,我的示例仍然有用。