问题:获取Python中当前脚本的名称
我正在尝试获取当前正在运行的Python脚本的名称。
我有一个名为的脚本foo.py
,我想做这样的事情以获得脚本名称:
print Scriptname
I’m trying to get the name of the Python script that is currently running.
I have a script called foo.py
and I’d like to do something like this in order to get the script name:
print Scriptname
回答 0
您可以使用__file__
获取当前文件的名称。在主模块中使用时,这是最初调用的脚本的名称。
如果要省略目录部分(可能存在),可以使用os.path.basename(__file__)
。
You can use __file__
to get the name of the current file. When used in the main module, this is the name of the script that was originally invoked.
If you want to omit the directory part (which might be present), you can use 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
。)
import sys
print sys.argv[0]
This will print foo.py
for python foo.py
, dir/foo.py
for python dir/foo.py
, etc. It’s the first argument to python
. (Note that after py2exe it would be foo.exe
.)
回答 2
For completeness’ sake, I thought it would be worthwhile summarizing the various possible outcomes and supplying references for the exact behaviour of each:
__file__
is the currently executing file, as detailed in the official documentation:
__file__
is the pathname of the file from which the module was loaded, if it was loaded from a file. The __file__
attribute may be missing for certain types of modules, such as C modules that are statically linked into the interpreter; for extension modules loaded dynamically from a shared library, it is the pathname of the shared library file.
From Python3.4 onwards, per issue 18416, __file__
is always an absolute path, unless the currently executing file is a script that has been executed directly (not via the interpreter with the -m
command line option) using a relative path.
__main__.__file__
(requires importing __main__
) simply accesses the aforementioned __file__
attribute of the main module, e.g. of the script that was invoked from the command line.
sys.argv[0]
(requires importing sys
) is the script name that was invoked from the command line, and might be an absolute path, as detailed in the official documentation:
argv[0]
is the script name (it is operating system dependent whether this is a full pathname or not). If the command was executed using the -c
command line option to the interpreter, argv[0]
is set to the string '-c'
. If no script name was passed to the Python interpreter, argv[0]
is the empty string.
As mentioned in another answer to this question, Python scripts that were converted into stand-alone executable programs via tools such as py2exe or PyInstaller might not display the desired result when using this approach (i.e. sys.argv[0]
would hold the name of the executable rather than the name of the main Python file within that executable).
If none of the aforementioned options seem to work, probably due to an irregular import operation, the inspect module might prove useful. In particular, invoking inspect.getfile(...)
on inspect.currentframe()
could work, although the latter would return None
when running in an implementation without Python stack frame.
Handling symbolic links
If the current script is a symbolic link, then all of the above would return the path of the symbolic link rather than the path of the real file and os.path.realpath(...)
should be invoked in order to extract the latter.
os.path.basename(...)
may be invoked on any of the above in order to extract the actual file name and os.path.splitext(...)
may be invoked on the actual file name in order to truncate its suffix, as in os.path.splitext(os.path.basename(...))
.
From Python 3.4 onwards, per PEP 428, the PurePath
class of the pathlib
module may be used as well on any of the above. Specifically, pathlib.PurePath(...).name
extracts the actual file name and pathlib.PurePath(...).stem
extracts the actual file name without its suffix.
回答 3
注意 __file__
将提供此代码所在的文件,该文件可以导入,并且与要解释的主文件不同。要获取主文件,可以使用特殊的__main__模块:
import __main__ as main
print(main.__file__)
注意 __main__.__file__
在Python 2.7中有效,但在3.2中无效,因此请使用上述import-as语法使其具有可移植性。
Note that __file__
will give the file where this code resides, which can be imported and different from the main file being interpreted. To get the main file, the special __main__ module can be used:
import __main__ as main
print(main.__file__)
Note that __main__.__file__
works in Python 2.7 but not in 3.2, so use the import-as syntax as above to make it portable.
回答 4
上述答案是好的。但是我发现使用上面的结果这种方法更有效。
这导致实际的脚本文件名不是路径。
import sys
import os
file_name = os.path.basename(sys.argv[0])
The Above answers are good . But I found this method more efficient using above results.
This results in actual script file name not a path.
import sys
import os
file_name = os.path.basename(sys.argv[0])
回答 5
对于现代Python版本(3.4+),Path(__file__).name
应该更加惯用。另外,Path(__file__).stem
为您提供不带.py
扩展名的脚本名称。
For modern Python versions (3.4+), Path(__file__).name
should be more idiomatic. Also, Path(__file__).stem
gives you the script name without the .py
extension.
回答 6
回答 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
Note: If you are using Python 3+, then you should use the print() function instead
Assuming that the filename is foo.py
, the below snippet
import sys
print sys.argv[0][:-3]
or
import sys
print sys.argv[0][::-1][3:][::-1]
As for other extentions with more characters, for example the filename foo.pypy
import sys
print sys.argv[0].split('.')[0]
If you want to extract from an absolute path
import sys
print sys.argv[0].split('/')[-1].split('.')[0]
will output foo
回答 8
sys中的第一个参数将是当前文件名,因此它将起作用
import sys
print sys.argv[0] # will print the file name
The first argument in sys will be the current file name so this will work
import sys
print sys.argv[0] # will print the file name
回答 9
如果您执行的是异常导入(例如,这是一个选项文件),请尝试:
import inspect
print (inspect.getfile(inspect.currentframe()))
请注意,这将返回文件的绝对路径。
If you’re doing an unusual import (e.g., it’s an options file), try:
import inspect
print (inspect.getfile(inspect.currentframe()))
Note that this will return the absolute path to the file.
回答 10
我们可以尝试使用此命令来获取当前脚本名称(不带扩展名)。
import os
script_name = os.path.splitext(os.path.basename(__file__))[0]
we can try this to get current script name without extension.
import os
script_name = os.path.splitext(os.path.basename(__file__))[0]
回答 11
由于OP要求提供当前脚本文件的名称,所以我希望
import os
os.path.split(sys.argv[0])[1]
Since the OP asked for the name of the current script file I would prefer
import os
os.path.split(sys.argv[0])[1]
回答 12
我快速的肮脏解决方案:
__file__.split('/')[-1:][0]
My fast dirty solution:
__file__.split('/')[-1:][0]
回答 13
回答 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确定进程的名称”。
all that answers are great, but have some problems You might not see at the first glance.
lets define what we want – we want the name of the script that was executed, not the name of the current module – so __file__
will only work if it is used in the executed script, not in an imported module.
sys.argv
is also questionable – what if your program was called by pytest ? or pydoc runner ? or if it was called by uwsgi ?
and – there is a third method of getting the script name, I havent seen in the answers – You can inspect the stack.
Another problem is, that You (or some other program) can tamper around with sys.argv
and __main__.__file__
– it might be present, it might be not. It might be valid, or not. At least You can check if the script (the desired result) exists !
my library bitranox/lib_programname at github does exactly that :
- check if
__main__
is present
- check if
__main__.__file__
is present
- does give
__main__.__file__
a valid result (does that script exist ?)
- if not: check sys.argv:
- is there pytest, docrunner, etc in the sys.argv ? –> if yes, ignore that
- can we get a valid result here ?
- if not: inspect the stack and get the result from there possibly
- if also the stack does not give a valid result, then throw an Exception.
by that way, my solution is working so far with setup.py test
, uwsgi
, pytest
, pycharm pytest
, pycharm docrunner (doctest)
, dreampie
, eclipse
there is also a nice blog article about that problem from Dough Hellman, “Determining the Name of a Process from Python”
回答 15
As of Python 3.5 you can simply do:
from pathlib import Path
Path(__file__).stem
See more here: https://docs.python.org/3.5/library/pathlib.html#pathlib.PurePath.stem
For example, I have a file under my user directory named test.py
with this inside:
from pathlib import Path
print(Path(__file__).stem)
print(__file__)
running this outputs:
>>> python3.6 test.py
test
test.py