获取当前脚本的名称Python

659 投票
14 回答
569504 浏览
提问于 2025-04-16 06:53

我想获取当前正在运行的Python脚本的名字。

我有一个叫做 foo.py 的脚本,我想用类似下面的方式来获取这个脚本的名字:

print(Scriptname)

14 个回答

159

为了让大家更清楚,我觉得有必要总结一下可能的结果,并提供每种情况的具体行为参考。

这个回答分为四个部分:

  1. 列出几种方法,可以获取当前正在执行的脚本的完整路径。

  2. 关于相对路径处理的注意事项。

  3. 关于符号链接处理的建议。

  4. 介绍几种方法,可以从完整路径中提取实际的文件名,包括文件后缀或不包括文件后缀。


提取完整文件路径

  • __file__ 是当前正在执行的文件,具体内容可以参考官方文档

    __file__ 是模块加载的文件路径,如果是从文件加载的模块。对于某些类型的模块,比如静态链接到解释器的C模块,可能没有__file__属性;而对于从共享库动态加载的扩展模块,它就是共享库文件的路径。

    Python3.4 开始,根据18416号问题__file__ 总是一个绝对路径,除非当前执行的文件是通过相对路径直接执行的脚本(而不是通过解释器使用-m命令行选项执行的)。

  • __main__.__file__(需要导入__main__)简单地访问上述__file__属性,指的是从命令行调用的脚本的主模块

    Python3.9 开始,根据20443号问题__main__模块的__file__属性变成了绝对路径,而不是相对路径。

  • sys.argv[0](需要导入sys)是从命令行调用的脚本名称,可能是绝对路径,具体内容可以参考官方文档

    argv[0] 是脚本名称(这是否是完整路径取决于操作系统)。如果命令是通过解释器的-c命令行选项执行的,argv[0] 会被设置为字符串'-c'。如果没有传递脚本名称给Python解释器,argv[0] 就是空字符串。

    正如在另一个回答中提到的,通过像py2exePyInstaller这样的工具将Python脚本转换为独立可执行程序时,使用这种方法可能无法得到想要的结果(即sys.argv[0]会包含可执行文件的名称,而不是该可执行文件内主Python文件的名称)。

  • 如果上述选项都不奏效,可能是由于不寻常的执行过程或不规则的导入操作,可以尝试使用inspect模块,正如在另一个回答中提到的

    import inspect
    source_file_path = inspect.getfile(inspect.currentframe())
    

    不过,inspect.currentframe() 在没有Python堆栈帧的实现中会引发异常。

    请注意,inspect.getfile(...)inspect.getsourcefile(...)更受欢迎,因为后者在只能确定二进制文件而不是对应源文件时,会引发TypeError异常(另见另一个问题的回答)。

  • Python3.6开始,正如在另一个回答中提到的,可以安装一个外部开源库lib_programname,它专门提供这个问题的完整解决方案。

    这个库会遍历上述所有方法,直到返回一个有效的路径。如果所有方法都失败,它会引发异常。它还尝试解决各种陷阱,比如通过pytest框架或pydoc模块的调用。

    import lib_programname
    # this returns the fully resolved path to the launched python program
    path_to_program = lib_programname.get_path_executed_script()  # type: pathlib.Path
    


处理相对路径

在处理返回相对路径的方法时,可能会想调用各种路径处理函数,比如os.path.abspath(...)os.path.realpath(...)来提取完整路径或真实路径。

然而,这些方法依赖于当前路径来推导完整路径。因此,如果程序先通过os.chdir(...)改变当前工作目录,然后再调用这些方法,它们就会返回错误的路径。


处理符号链接

如果当前脚本是一个符号链接,那么上述所有方法都会返回符号链接的路径,而不是实际文件的路径,这时应该调用os.path.realpath(...)来提取实际文件的路径。


进一步提取实际文件名的方法

可以在上述任意方法上调用os.path.basename(...)来提取实际文件名,并且可以在实际文件名上调用os.path.splitext(...)来去掉文件后缀,比如使用os.path.splitext(os.path.basename(...))

Python 3.4开始,根据PEP 428,可以使用PurePath类,作为上述方法的替代。具体来说,pathlib.PurePath(...).name可以提取实际文件名,而pathlib.PurePath(...).stem可以提取不带后缀的实际文件名。

240
import sys
print(sys.argv[0])

这段话的意思是,当你输入 python foo.py 时,它会显示 foo.py,而输入 python dir/foo.py 时,它会显示 dir/foo.py,等等。这里提到的就是你给 python 的第一个参数。(注意,如果你用的是 py2exe,那么它会变成 foo.exe。)

950

你可以使用 __file__ 来获取当前文件的名字。当在主模块中使用时,这个名字就是最开始运行的脚本的名字。

如果你想去掉文件路径中的目录部分(可能会有),可以使用 os.path.basename(__file__)

撰写回答