如何正确确定当前脚本目录?

409 投票
16 回答
188312 浏览
提问于 2025-04-16 04:10

我想知道在Python中,如何找到当前脚本所在的目录是最好的方法。

我发现,由于调用Python代码的方式有很多,所以很难找到一个好的解决方案。

这里有一些问题:

  • __file__ 在用 execexecfile 执行脚本时是没有定义的。
  • __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__))

这确实是你能得到的最好结果。

execexecfile 来执行脚本是比较少见的;通常你应该使用模块的方式来加载脚本。如果你真的需要用这些方法,我建议你在传给脚本的 globals 中设置 __file__,这样脚本就能读取到这个文件名。

在执行的代码中没有其他方法可以获取文件名:正如你所提到的,当前工作目录可能在一个完全不同的地方。

撰写回答