I run a python shell from crontab every minute:
我每分钟从crontab运行一个python shell:
* * * * * /home/udi/foo/bar.py
/home/udi/foo
has some necessary subdirectories, like /home/udi/foo/log
and /home/udi/foo/config
, which /home/udi/foo/bar.py
refers to.
/home/udi/foo有一些必要的子目录,如/home/udi/foo/log和/home/udi/foo/config,其中/home/ udi/foo/bar。py是指。
The problem is that crontab
runs the script from a different working directory, so trying to open ./log/bar.log
fails.
问题是crontab从不同的工作目录运行脚本,所以要尝试打开./log/bar。登录失败。
Is there a nice way to tell the script to change the working directory to the script's own directory? I would fancy a solution that would work for any script location, rather than explicitly telling the script where it is.
是否有一种很好的方法可以告诉脚本将工作目录更改为脚本自己的目录?我希望有一个适用于任何脚本位置的解决方案,而不是显式地告诉脚本在哪里。
EDIT:
编辑:
os.chdir(os.path.dirname(sys.argv[0]))
Was the most compact elegant solution. Thanks for your answers and explanations!
是最紧凑、最优雅的解决方案。谢谢你的回答和解释!
4 个解决方案
#1
140
This will change your current working directory to so that opening relative paths will work:
这将更改您当前的工作目录,以便打开相关路径:
import os
os.chdir("/home/udi/foo")
However, you asked how to change into whatever directory your Python script is located, even if you don't know what directory that will be when you're writing your script. To do this, you can use the os.path
functions:
但是,您会问如何将其更改为Python脚本所在的任何目录,即使您在编写脚本时不知道该目录是哪个目录。为此,您可以使用os。路径功能:
import os
abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
os.chdir(dname)
This takes the filename of your script, converts it to an absolute path, then extracts the directory of that path, then changes into that directory.
这将获取脚本的文件名,将其转换为绝对路径,然后提取该路径的目录,然后更改为该目录。
#2
30
You can get a shorter version by using sys.path[0]
.
通过使用sys.path[0]可以获得更短的版本。
os.chdir(sys.path[0])
From http://docs.python.org/library/sys.html#sys.path
从http://docs.python.org/library/sys.html sys.path
As initialized upon program startup, the first item of this list,
path[0]
, is the directory containing the script that was used to invoke the Python interpreter当程序启动时初始化时,这个列表的第一项path[0]是包含用于调用Python解释器的脚本的目录
#3
16
Don't do this.
不要这样做。
Your scripts and your data should not be mashed into one big directory. Put your code in some known location (site-packages
or /var/opt/udi
or something) separate from your data. Use good version control on your code to be sure that you have current and previous versions separated from each other so you can fall back to previous versions and test future versions.
脚本和数据不应该被压缩到一个大目录中。将您的代码放入一些已知的位置(站点包或/var/opt/udi或其他东西)与您的数据分离。在你的代码中使用好的版本控制,确保你有当前和以前版本之间的分离,这样你就可以回到以前的版本和测试未来版本。
Bottom line: Do not mingle code and data.
底线:不要混合代码和数据。
Data is precious. Code comes and goes.
数据是宝贵的。代码来了又去。
Provide the working directory as a command-line argument value. You can provide a default as an environment variable. Don't deduce it (or guess at it)
提供工作目录作为命令行参数值。您可以提供一个默认的环境变量。不要推断(或猜测)
Make it a required argument value and do this.
使它成为一个必需的参数值,并这样做。
import sys
import os
working= os.environ.get("WORKING_DIRECTORY","/some/default")
if len(sys.argv) > 1: working = sys.argv[1]
os.chdir( working )
Do not "assume" a directory based on the location of your software. It will not work out well in the long run.
不要根据软件的位置“假设”一个目录。从长远来看,这是行不通的。
#4
13
Change your crontab command to
将crontab命令更改为
* * * * * (cd /home/udi/foo/ || exit 1; ./bar.py)
The (...)
starts a sub-shell that your crond executes as a single command. The || exit 1
causes your cronjob to fail in case that the directory is unavailable.
(…)启动子shell,您的crond作为单个命令执行。||出口1使您的cronjob失败,以防该目录不可用。
Though the other solutions may be more elegant in the long run for your specific scripts, my example could still be useful in cases where you can't modify the program or command that you want to execute.
尽管从长远来看,其他解决方案可能更适合您的特定脚本,但在您无法修改希望执行的程序或命令的情况下,我的示例仍然很有用。
#1
140
This will change your current working directory to so that opening relative paths will work:
这将更改您当前的工作目录,以便打开相关路径:
import os
os.chdir("/home/udi/foo")
However, you asked how to change into whatever directory your Python script is located, even if you don't know what directory that will be when you're writing your script. To do this, you can use the os.path
functions:
但是,您会问如何将其更改为Python脚本所在的任何目录,即使您在编写脚本时不知道该目录是哪个目录。为此,您可以使用os。路径功能:
import os
abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
os.chdir(dname)
This takes the filename of your script, converts it to an absolute path, then extracts the directory of that path, then changes into that directory.
这将获取脚本的文件名,将其转换为绝对路径,然后提取该路径的目录,然后更改为该目录。
#2
30
You can get a shorter version by using sys.path[0]
.
通过使用sys.path[0]可以获得更短的版本。
os.chdir(sys.path[0])
From http://docs.python.org/library/sys.html#sys.path
从http://docs.python.org/library/sys.html sys.path
As initialized upon program startup, the first item of this list,
path[0]
, is the directory containing the script that was used to invoke the Python interpreter当程序启动时初始化时,这个列表的第一项path[0]是包含用于调用Python解释器的脚本的目录
#3
16
Don't do this.
不要这样做。
Your scripts and your data should not be mashed into one big directory. Put your code in some known location (site-packages
or /var/opt/udi
or something) separate from your data. Use good version control on your code to be sure that you have current and previous versions separated from each other so you can fall back to previous versions and test future versions.
脚本和数据不应该被压缩到一个大目录中。将您的代码放入一些已知的位置(站点包或/var/opt/udi或其他东西)与您的数据分离。在你的代码中使用好的版本控制,确保你有当前和以前版本之间的分离,这样你就可以回到以前的版本和测试未来版本。
Bottom line: Do not mingle code and data.
底线:不要混合代码和数据。
Data is precious. Code comes and goes.
数据是宝贵的。代码来了又去。
Provide the working directory as a command-line argument value. You can provide a default as an environment variable. Don't deduce it (or guess at it)
提供工作目录作为命令行参数值。您可以提供一个默认的环境变量。不要推断(或猜测)
Make it a required argument value and do this.
使它成为一个必需的参数值,并这样做。
import sys
import os
working= os.environ.get("WORKING_DIRECTORY","/some/default")
if len(sys.argv) > 1: working = sys.argv[1]
os.chdir( working )
Do not "assume" a directory based on the location of your software. It will not work out well in the long run.
不要根据软件的位置“假设”一个目录。从长远来看,这是行不通的。
#4
13
Change your crontab command to
将crontab命令更改为
* * * * * (cd /home/udi/foo/ || exit 1; ./bar.py)
The (...)
starts a sub-shell that your crond executes as a single command. The || exit 1
causes your cronjob to fail in case that the directory is unavailable.
(…)启动子shell,您的crond作为单个命令执行。||出口1使您的cronjob失败,以防该目录不可用。
Though the other solutions may be more elegant in the long run for your specific scripts, my example could still be useful in cases where you can't modify the program or command that you want to execute.
尽管从长远来看,其他解决方案可能更适合您的特定脚本,但在您无法修改希望执行的程序或命令的情况下,我的示例仍然很有用。