获取Python中当前脚本的名称

问题:获取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.pypython foo.pydir/foo.pypython 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

为了完整起见,我认为值得总结各种可能的结果,并为每种结果的确切行为提供参考:

  • __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的是被通过的工具,如转换成独立的可执行程序的脚本py2exePyInstaller可能不会显示预期的结果使用这种方法的时候(也就是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提取不带后缀的实际文件名。

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.


Further manipulations that extract the actual file name

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

尝试这个:

print __file__

Try this:

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

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

os.path.abspath(__file__)将为您提供一条绝对路径(也relpath()可用)。

sys.argv[-1] 会给你一个相对的路径。

os.path.abspath(__file__) will give you an absolute path (relpath() available as well).

sys.argv[-1] will give you a relative path.


回答 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 testuwsgipytestpycharm pytestpycharm docrunner (doctest)dreampieeclipse

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

从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

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