我正在尝试获取当前正在运行的Python脚本的名称。
例如,我有一个名为foo.py
的脚本,我想在其中执行类似的操作:
print Scriptname
并获取:foo.py
。
答案 0 :(得分:464)
使用__file__
。如果要省略目录部分(可能存在),可以使用os.path.basename(__file__)
。
答案 1 :(得分:111)
import sys
print sys.argv[0]
这将为foo.py
打印python foo.py
,为dir/foo.py
打印python dir/foo.py
等。这是python
的第一个参数。 (请注意,在py2exe之后它将是foo.exe
。)
答案 2 :(得分:56)
请注意,__file__
将提供此代码所在的文件,该文件可以导入,与正在解释的主文件不同。要获取主文件,可以使用特殊的__main__模块:
import __main__ as main
print(main.__file__)
请注意__main__.__file__
适用于Python 2.7,但不适用于3.2,因此请使用上面的import-as语法使其可移植。
答案 3 :(得分:45)
为了完整起见,我认为总结各种可能的结果并为每种结果的确切行为提供参考是值得的:
__file__
是当前正在执行的文件,详见official documentation:
__file__
是加载模块的文件的路径名(如果是从文件加载的)。某些类型的模块可能缺少__file__
属性,例如静态链接到解释器的 C 模块;对于从共享库动态加载的扩展模块,它是共享库文件的路径名。
From Python3.4以后,每issue 18416,__file__
始终是绝对路径,除非当前正在执行的文件是直接执行的脚本(不是通过{{{ 1}}命令行选项)使用相对路径。
-m
(需要导入__main__.__file__
)只需访问main module的上述__main__
属性,例如从命令行调用的脚本。
__file__
(需要导入sys.argv[0]
)是从命令行调用的脚本名称,可能是绝对路径,详见official documentation:< / p>
sys
是脚本名称(无论这是否是完整路径名,它依赖于操作系统)。如果使用解释器的argv[0]
命令行选项执行命令,则-c
将设置为字符串argv[0]
。如果没有脚本名称传递给Python解释器,'-c'
是空字符串。
如another answer to this question中所述,通过py2exe或PyInstaller等工具转换为独立可执行程序的 Python 脚本可能无法显示所需内容使用此方法时的结果(即argv[0]
将保存可执行文件的名称,而不是该可执行文件中主 Python 文件的名称。)
sys.argv[0]
以提取实际文件名。
答案 4 :(得分:36)
以上答案都很好。但是我发现这种方法使用上述结果更有效率 这导致实际的脚本文件名不是路径。
import sys
import os
file_name = os.path.basename(sys.argv[0])
答案 5 :(得分:6)
试试这个:
print __file__
答案 6 :(得分:6)
sys中的第一个参数将是当前文件名,因此可以使用
import sys
print sys.argv[0] # will print the file name
答案 7 :(得分:5)
如果您正在进行异常导入(例如,它是一个选项文件),请尝试:
import inspect
print (inspect.getfile(inspect.currentframe()))
请注意,这将返回文件的绝对路径。
答案 8 :(得分:5)
对于现代Python版本,Path(__file__).name
应该更加惯用。另外,Path(__file__).stem
会为您提供不带.py
扩展名的脚本名称。
答案 9 :(得分:5)
假设文件名是int
,则下面的代码段
foo.py
或
import sys
print sys.argv[0][:-3]
将输出import sys
print sys.argv[0][::-1][3:][::-1]
答案 10 :(得分:3)
我们可以尝试此操作以获取不带扩展名的当前脚本名称。
import os
script_name = os.path.splitext(os.path.basename(__file__))[0]
答案 11 :(得分:2)
从Python 3.5开始,您可以轻松做到:
from pathlib import Path
Path(__file__).stem
在此处查看更多信息:https://docs.python.org/3.5/library/pathlib.html#pathlib.PurePath.stem
例如,我的用户目录下有一个名为test.py
的文件,其内部为:
from pathlib import Path
print(Path(__file__).stem)
print(__file__)
运行以下输出:
>>> python3.6 test.py
test
test.py
答案 12 :(得分:2)
所有这些答案都很不错,但存在一些问题,您乍一看可能看不到。
let定义了我们想要的-我们想要执行的脚本的名称,而不是当前模块的名称-因此__file__
仅在已执行的脚本中使用,而不在导入的脚本中使用时才有效模块。
sys.argv
也值得怀疑-如果您的程序被pytest调用了怎么办?还是pydocRunner?还是被uwsgi调用?
而且-还有第三种获取脚本名称的方法,我没有在答案中看到-您可以检查堆栈。
另一个问题是,您(或某些其他程序)可以篡改sys.argv
和__main__.__file__
-它可能存在,但可能没有。它可能有效或无效。至少您可以检查脚本(期望的结果)是否存在!
库lib_programname正是这样做的:
__main__
__main__.__file__
__main__.__file__
一个有效的结果(该脚本存在吗?)通过这种方式,到目前为止,我的解决方案可以与setup.py test
,uwsgi
,pytest
,pycharm pytest
,pycharm docrunner (doctest)
,dreampie
, eclipse
Dough Hellman上也有一篇有关该问题的不错的博客文章,“用Python确定进程的名称”
顺便说一句,它将在python 3.9中再次更改: main 模块的 file 属性变为绝对路径,而不是相对路径。现在,通过os.chdir()更改当前目录后,这些路径仍然有效。
所以我宁愿照顾一个小模块,而不是在需要更改代码的情况下浏览我的代码库...
免责声明:我是lib_programname库的作者。
答案 13 :(得分:1)
由于OP要求提供当前脚本文件的名称,所以
import os
os.path.split(sys.argv[0])[1]
答案 14 :(得分:0)
我的快速解决方案:
__file__.split('/')[-1:][0]
答案 15 :(得分:0)
os.path.abspath(__file__)
将为您提供绝对路径(relpath()
也可用)。
sys.argv[-1]
将为您提供相对路径。
答案 16 :(得分:0)
您可以执行此操作而无需导入os或其他库。
如果要获取当前python脚本的路径,请使用:__file__
如果只想获取不带.py扩展名的文件名,请使用以下命令:
__file__.rsplit("/", 1)[1].split('.')[0]
答案 17 :(得分:-2)
def basename():
x=__file__
y=x.split('\\')
y1=y[-1]
y2=y1.split('.')
y3=y2[0]
return(y2[0])