Answers:
您可以使用__file__
获取当前文件的名称。在主模块中使用时,这是最初调用的脚本的名称。
如果要省略目录部分(可能存在),可以使用os.path.basename(__file__)
。
__file__
在交互式解释器中未定义,因为它在那里没有意义。它是由导入实现设置的,因此,如果您使用非标准的导入机制,则可能也未设置它。
import os
是必需的。我将此添加到答案中。
import os
和import os.path
完全等效。
import sys
print sys.argv[0]
这将打印foo.py
的python foo.py
,dir/foo.py
对python dir/foo.py
等,这是第一个参数python
。(请注意,在py2exe之后将会是foo.exe
。)
python linkfile.py
,这里linkfile.py
是一个符号realfile.py
,sys.argv[0]
将是'linkfile.py'
,这可能是也可能不是你想要的是; 这当然是我所期望的。__file__
是一样的:它将是linkfile.py
。如果你想找到'realfile.py'
的'linkfile.py'
,试试os.path.realpath('linkfile.py')
。
__file__
而是使用。
为了完整起见,我认为值得总结各种可能的结果,并为每种结果的确切行为提供参考:
__file__
是当前正在执行的文件,如官方文档中所述:
__file__
是从中加载模块的文件的路径名(如果它是从文件加载的)。所述__file__
属性可以是缺少某些类型的模块,如Ç静态链接到解释器模块; 对于从共享库动态加载的扩展模块,它是共享库文件的路径名。
从Python3.4起,每发行18416,__file__
始终是一个绝对路径,除非当前正在执行的文件是已经被直接执行(不通过与解释脚本-m
使用相对路径命令行选项)。
__main__.__file__
(需要import __main__
)仅访问主模块的上述__file__
属性,例如,从命令行调用的脚本的属性。
sys.argv[0]
(需要import sys
)是从命令行调用的脚本名称,并且可能是绝对路径,如官方文档中所述:
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.basename(...)
可以在上述任何方法上调用以便提取实际的文件名,os.path.splitext(...)
也可以在实际的文件名上调用以便截断其后缀,如中所示os.path.splitext(os.path.basename(...))
。
从Python的3.4起,每PEP 428中,PurePath
类的的pathlib
模块可以用作以及任何上述的。具体来说,pathlib.PurePath(...).name
提取实际文件名并pathlib.PurePath(...).stem
提取不带后缀的实际文件名。
注意 __file__
将提供此代码所在的文件,该文件可以导入,并且与要解释的主文件不同。要获取主文件,可以使用特殊的__main__模块:
import __main__ as main
print(main.__file__)
注意 __main__.__file__
在Python 2.7中有效,但在3.2中无效,因此请使用上述import-as语法使其具有可移植性。
rPython
包时却无法使用R
。那肯定是一个异常情况,很难处理。
__main__
内部导入,用于在R
和之间传递变量python
,因此__main__.__file__
在调用其他任何东西之前将其设置起来相对容易,但是我什至不确定这种情况下合适的值。
上述答案是好的。但是我发现使用上面的结果这种方法更有效。
这导致实际的脚本文件名不是路径。
import sys
import os
file_name = os.path.basename(sys.argv[0])
对于现代Python版本(3.4+),Path(__file__).name
应该更加惯用。另外,Path(__file__).stem
为您提供不带.py
扩展名的脚本名称。
from pathlib import Path
先。
pathlib
是Python 3.4中引入的,因此它应该从Python 3.4开始运行。
假设文件名为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
如果您执行的是异常导入(例如,这是一个选项文件),请尝试:
import inspect
print (inspect.getfile(inspect.currentframe()))
请注意,这将返回文件的绝对路径。
我们可以尝试使用此命令来获取当前脚本名称(不带扩展名)。
import os
script_name = os.path.splitext(os.path.basename(__file__))[0]
os.path.abspath(__file__)
将为您提供一条绝对路径(也relpath()
可用)。
sys.argv[-1]
会给你一个相对的路径。
所有这些答案都很不错,但是有一些问题,您乍一看可能看不到。
让我们定义我们想要的-我们想要执行的脚本的名称,而不是当前模块的名称-因此,__file__
只有在已执行的脚本中使用了它,而不是在导入的模块中使用它时,它才起作用。
sys.argv
也是可疑的-如果您的程序被pytest调用了怎么办?还是pydocRunner?还是被uwsgi调用?
-还有第三种获取脚本名称的方法,我在答案中没有看到-您可以检查堆栈。
另一个问题是,您(或某些其他程序)可以篡改sys.argv
并且__main__.__file__
-它可能存在,但可能不存在。它可能有效或无效。至少您可以检查脚本(所需结果)是否存在!
我在github上的库bitranox / lib_programname确实做到了:
__main__
存在__main__.__file__
存在__main__.__file__
有效结果(该脚本是否存在?)通过这种方式,我的解决方案正在到目前为止有setup.py test
,uwsgi
,pytest
,pycharm pytest
,pycharm docrunner (doctest)
,dreampie
,eclipse
Dough Hellman也有一篇关于该问题的不错的博客文章,“用Python确定进程的名称”。
从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
Exception NameError: NameError("global name '__file__' is not defined",)
”