如何正确确定当前脚本目录?
我想知道在Python中,如何找到当前脚本所在的目录是最好的方法。
我发现,由于调用Python代码的方式有很多,所以很难找到一个好的解决方案。
这里有一些问题:
__file__
在用exec
或execfile
执行脚本时是没有定义的。__module__
只有在模块中才会被定义。
使用场景:
./myfile.py
python myfile.py
./somedir/myfile.py
python somedir/myfile.py
execfile('myfile.py')
(从另一个脚本中执行,这个脚本可能在不同的目录下,当前目录也可能不同。)
我知道没有完美的解决方案,但我在寻找能够解决大多数情况的最佳方法。
最常用的方法是 os.path.dirname(os.path.abspath(__file__))
,但如果你是通过另一个脚本用 exec()
执行这个脚本,这个方法就不管用了。
警告
任何使用当前目录的解决方案都会失败,因为当前目录可能会根据脚本的调用方式而不同,或者在运行的脚本中被更改。
16 个回答
67
在Python 3.4及以上版本中,你可以使用更简单的 pathlib
模块:
from inspect import currentframe, getframeinfo
from pathlib import Path
filename = getframeinfo(currentframe()).filename
parent = Path(filename).resolve().parent
你也可以使用 __file__
(当它可用时)来完全避免使用 inspect
模块:
from pathlib import Path
parent = Path(__file__).resolve().parent
153
如果你想处理一个脚本是通过 execfile(...)
这个方式被调用的情况,你可以使用 inspect
模块来推断出文件名(包括路径)。据我所知,这个方法可以适用于你列出的所有情况:
filename = inspect.getframeinfo(inspect.currentframe()).filename
path = os.path.dirname(os.path.abspath(filename))
329
os.path.dirname(os.path.abspath(__file__))
这确实是你能得到的最好结果。
用 exec
或 execfile
来执行脚本是比较少见的;通常你应该使用模块的方式来加载脚本。如果你真的需要用这些方法,我建议你在传给脚本的 globals
中设置 __file__
,这样脚本就能读取到这个文件名。
在执行的代码中没有其他方法可以获取文件名:正如你所提到的,当前工作目录可能在一个完全不同的地方。