问题:获取Python中当前脚本的名称
我正在尝试获取当前正在运行的Python脚本的名称。
我有一个名为的脚本foo.py
,我想做这样的事情以获得脚本名称:
print Scriptname
回答 0
您可以使用__file__
获取当前文件的名称。在主模块中使用时,这是最初调用的脚本的名称。
如果要省略目录部分(可能存在),可以使用os.path.basename(__file__)
。
回答 1
import sys
print sys.argv[0]
这将打印foo.py
的python foo.py
,dir/foo.py
对python dir/foo.py
等,这是第一个参数python
。(请注意,在py2exe之后将会是foo.exe
。)
回答 2
为了完整起见,我认为值得总结各种可能的结果,并为每种结果的确切行为提供参考:
__file__
是当前正在执行的文件,如官方文档中所述:__file__
是从中加载模块的文件的路径名(如果它是从文件加载的)。所述__file__
属性可以是缺少某些类型的模块,如Ç静态链接到解释器模块; 对于从共享库动态加载的扩展模块,它是共享库文件的路径名。从Python3.4起,每发行18416,
__file__
始终是一个绝对路径,除非当前正在执行的文件是已经被直接执行(不通过与解释脚本-m
使用相对路径命令行选项)。__main__.__file__
(需要import__main__
)仅访问主模块的上述__file__
属性,例如,从命令行调用的脚本的属性。sys.argv[0]
(需要importsys
)是从命令行调用的脚本名称,并且可能是绝对路径,如官方文档中所述:argv[0]
是脚本名称(是否为完整路径名取决于操作系统)。如果命令是使用-c
解释器的命令行选项执行的,argv[0]
则将其设置为字符串'-c'
。如果没有脚本名称传递给Python解释器,argv[0]
则为空字符串。正如提到的另一个回答这个问题,Python的是被通过的工具,如转换成独立的可执行程序的脚本py2exe或PyInstaller可能不会显示预期的结果使用这种方法的时候(也就是
sys.argv[0]
将持有的可执行文件的名称,而不是名称该可执行文件中主要Python文件的名称)。如果上述选项似乎都不起作用,可能是由于不规则的导入操作造成的,那么检查模块可能会证明是有用的。特别是,在调用
inspect.getfile(...)
上inspect.currentframe()
可以工作,尽管后者将返回None
没有实现运行时的Python堆栈帧。
处理符号链接
如果当前脚本是符号链接,则以上所有内容都将返回符号链接的路径,而不是真实文件的路径,因此os.path.realpath(...)
应调用它们以提取后者。
提取实际文件名的进一步操作
os.path.splitext(os.path.basename(...))
。
从Python的3.4起,每PEP 428中,PurePath
类的的pathlib
模块可以用作以及任何上述的。具体来说,pathlib.PurePath(...).name
提取实际文件名并pathlib.PurePath(...).stem
提取不带后缀的实际文件名。
回答 3
注意 __file__
将提供此代码所在的文件,该文件可以导入,并且与要解释的主文件不同。要获取主文件,可以使用特殊的__main__模块:
import __main__ as main
print(main.__file__)
注意 __main__.__file__
在Python 2.7中有效,但在3.2中无效,因此请使用上述import-as语法使其具有可移植性。
回答 4
上述答案是好的。但是我发现使用上面的结果这种方法更有效。
这导致实际的脚本文件名不是路径。
import sys
import os
file_name = os.path.basename(sys.argv[0])
回答 5
对于现代Python版本(3.4+),Path(__file__).name
应该更加惯用。另外,Path(__file__).stem
为您提供不带.py
扩展名的脚本名称。
回答 6
尝试这个:
print __file__
回答 7
注意:如果您使用的是Python 3+,则应改用print()函数
假设文件名为foo.py
,则以下代码段
import sys
print sys.argv[0][:-3]
要么
import sys
print sys.argv[0][::-1][3:][::-1]
至于具有更多字符的其他扩展名,例如文件名 foo.pypy
import sys
print sys.argv[0].split('.')[0]
如果要从绝对路径中提取
import sys
print sys.argv[0].split('/')[-1].split('.')[0]
将输出 foo
回答 8
sys中的第一个参数将是当前文件名,因此它将起作用
import sys
print sys.argv[0] # will print the file name
回答 9
如果您执行的是异常导入(例如,这是一个选项文件),请尝试:
import inspect
print (inspect.getfile(inspect.currentframe()))
请注意,这将返回文件的绝对路径。
回答 10
我们可以尝试使用此命令来获取当前脚本名称(不带扩展名)。
import os
script_name = os.path.splitext(os.path.basename(__file__))[0]
回答 11
由于OP要求提供当前脚本文件的名称,所以我希望
import os
os.path.split(sys.argv[0])[1]
回答 12
我快速的肮脏解决方案:
__file__.split('/')[-1:][0]
回答 13
sys.argv[-1]
会给你一个相对的路径。
回答 14
所有这些答案都很不错,但是有一些问题,您乍一看可能看不到。
让我们定义我们想要的-我们想要执行的脚本的名称,而不是当前模块的名称-因此,__file__
只有在已执行的脚本中使用了它,而不是在导入的模块中使用它时,它才起作用。
sys.argv
也是可疑的-如果您的程序被pytest调用了怎么办?还是pydocRunner?还是被uwsgi调用?
-还有第三种获取脚本名称的方法,我在答案中没有看到-您可以检查堆栈。
另一个问题是,您(或某些其他程序)可以篡改sys.argv
并且__main__.__file__
-它可能存在,但可能不存在。它可能有效或无效。至少您可以检查脚本(所需结果)是否存在!
我在github上的库bitranox / lib_programname确实做到了:
- 检查是否
__main__
存在 - 检查是否
__main__.__file__
存在 - 确实给
__main__.__file__
有效结果(该脚本是否存在?) - 如果不是,请检查sys.argv:
- sys.argv中是否有pytest,docrunner等?->如果是,请忽略
- 我们可以在这里得到有效的结果吗?
- 如果不是:检查堆栈并从那里获取结果
- 如果堆栈也未给出有效结果,则抛出异常。
通过这种方式,我的解决方案正在到目前为止有setup.py test
,uwsgi
,pytest
,pycharm pytest
,pycharm docrunner (doctest)
,dreampie
,eclipse
Dough Hellman也有一篇关于该问题的不错的博客文章,“用Python确定进程的名称”。
回答 15
从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