如何在 Python 中获取 __main__ 模块的文件名?

Posted

技术标签:

【中文标题】如何在 Python 中获取 __main__ 模块的文件名?【英文标题】:How to get filename of the __main__ module in Python? 【发布时间】:2010-10-11 00:44:29 【问题描述】:

假设我有两个模块:

a.py:

import b
print __name__, __file__

b.py:

print __name__, __file__

我运行“a.py”文件。这打印:

b        C:\path\to\code\b.py
__main__ C:\path\to\code\a.py

问题:如何从“b.py”库中获取__main__ 模块(本例中为“a.py”)的路径?

【问题讨论】:

注意:这里的问题和许多答案都使用 Python 2 语法进行打印。对于 Python 3,在 print 的参数周围添加括号,因为它现在是一个函数。 【参考方案1】:
import __main__
print __main__.__file__

【讨论】:

整洁!重要的是要意识到需要导入 main - 我随机猜测并实际尝试了第二行,但它失败了 - 现在我知道为什么了。 __main__ 并不总是有 __file__ 属性。 +1 因为下面帖子的 cmets 中的 romkyns 请求。 @J.F.Sebastian 我们能否可靠地使用inspect.getfile(__main__) 来获取文件路径? @jpmc26:我不知道。要获取脚本的目录(不是其名称),您可以使用 get_script_dir()【参考方案2】:

也许这样可以解决问题:

import sys
from os import path
print path.abspath(sys.modules['__main__'].__file__)

请注意,为了安全起见,您应该检查__main__ 模块是否具有__file__ 属性。如果它是动态创建的,或者只是在交互式 python 控制台中运行,它不会有__file__

python
>>> import sys
>>> print sys.modules['__main__']
<module '__main__' (built-in)>
>>> print sys.modules['__main__'].__file__
AttributeError: 'module' object has no attribute '__file__'

一个简单的 hasattr() 检查将起到防范方案 2 的作用,如果这在您的应用中是可能的。

【讨论】:

奇妙吧!我很高兴能帮上忙。如果这确实回答了您的问题,您介意点击问题上的“接受”按钮吗? :-) 我恢复了更改...公平地说,ironfroggy 给出了最适合您的答案,我真的认为他应该得到唯一的荣誉。 假设主脚本没有__file__ 属性?那你怎么得到路径呢?您说要检查 main 是否具有 __file__ 属性,但是如果 main 没有该属性,您的代码不会显示该怎么做。【参考方案3】:

下面的 python 代码提供了额外的功能,包括它与py2exe 可执行文件无缝协作。

我使用类似的代码来查找相对于运行脚本的路径,即__main__。作为一个额外的好处,它可以跨平台工作,包括 Windows。

import imp
import os
import sys

def main_is_frozen():
   return (hasattr(sys, "frozen") or # new py2exe
           hasattr(sys, "importers") # old py2exe
           or imp.is_frozen("__main__")) # tools/freeze

def get_main_dir():
   if main_is_frozen():
       # print 'Running from path', os.path.dirname(sys.executable)
       return os.path.dirname(sys.executable)
   return os.path.dirname(sys.argv[0])

# find path to where we are running
path_to_script=get_main_dir()

# OPTIONAL:
# add the sibling 'lib' dir to our module search path
lib_path = os.path.join(get_main_dir(), os.path.pardir, 'lib')
sys.path.insert(0, lib_path)

# OPTIONAL: 
# use info to find relative data files in 'data' subdir
datafile1 = os.path.join(get_main_dir(), 'data', 'file1')

希望上面的示例代码可以提供更多关于如何确定运行脚本路径的信息...

【讨论】:

如果您在启动脚本和调用os.dirname(sys.argv[0]) 之间更改目录(使用os.chdir),结果将毫无意义。 我用来制作一个GLOBALS.py 模块,该模块至少由主脚本导入,它执行类似于上面的代码并将结果存储在变量MAINDIR 中,因此我可以访问GLOBALS.MAINDIR 来自任何其他模块,无需担心使用os.chdir 如果您想知道脚本的起始目录并且还想使用os.chdir(),则需要保存初始的os.getcwd()。由于用户在 Windows 上,我想演示一些仍然可以在 py2exe 和 freeze 的上下文中工作的东西。【参考方案4】:

另一种方法是使用sys.argv[0]

import os
import sys

main_file = os.path.realpath(sys.argv[0]) if sys.argv[0] else None

如果 Python 以 -c 开头或从 Python 控制台检查,sys.argv[0] 将是一个空字符串。

【讨论】:

如果 Python 使用 -c 选项启动,或者如果从 Python 控制台检查 sys.argv[0],您如何获得 __main__ 模块的路径?【参考方案5】:
import sys, os

def getExecPath():
    try:
        sFile = os.path.abspath(sys.modules['__main__'].__file__)
    except:
        sFile = sys.executable
    return os.path.dirname(sFile)

此函数适用于 Python 和 Cython 编译的程序。

【讨论】:

以上是关于如何在 Python 中获取 __main__ 模块的文件名?的主要内容,如果未能解决你的问题,请参考以下文章

__name__ == '__main__'

如何在 Python3 中使用带有 if __name__='__main__' 块的相对导入?

(转)Python中如何理解if __name__ == '__main__'

在python中如何让模块中的函数枚举__main__中的变量?

Python 中的 if __name__ == '__main__' 该如何理解

如何在 Windows 10 中从 bash 提示符运行 python '__main__' 程序文件?