如何获取当前运行模块的路径/名称

44 投票
8 回答
69182 浏览
提问于 2025-04-16 12:56

我搜索了一下,这似乎是个简单的问题,但没有简单的答案。

我有一个文件 a/b/c.py,它是通过 python -m a.b.c 来调用的。我想在模块级别获取值 a.b.c

USAGE = u'''\
Usage:
    python -m %s -h
''' % (what_do_i_put_here,)

所以当我收到 -h 这个选项时,我可以显示 USAGE,而不需要在每个脚本里都写下实际的值。

我真的需要用 inspect 来获取这个值吗?

谢谢。

编辑:如我所说,虽然有一些答案(我查过了),但都不简单。要么使用 inspect,要么使用 traceback,或者操作 __file____package__,然后做一些字符串处理来得到答案。但没有什么像我在模块里有个类时,可以直接用 myClass.__module__ 就能得到我想要的答案那么简单。使用 __name__ 是没用的,因为它总是显示 "__main__"

另外,这个是在 Python 2.6 中,我不能使用其他版本。

8 个回答

10

当使用 -m 选项运行时,sys.path[0] 会包含模块的完整路径。你可以利用这个路径来构建模块的名称。

来源: http://docs.python.org/using/cmdline.html#command-line

另一个选择是可以在模块中使用的内置变量 __package__

19

我觉得你其实是在寻找一个叫做 __name__ 的特殊变量。根据Python文档的说法:

在一个模块内部,模块的名字(以字符串形式)可以通过全局变量 __name__ 来获取。

如果你直接运行一个文件,这个名字会是 __main__。但是,如果你在一个模块里面(比如使用了 -m 这个标志,或者其他的导入方式),它就会是模块的完整名称。

31

这个对我来说有效:

__loader__.fullname

另外,如果我从 a\ 目录运行 python -m b.c,结果也会得到 'b.c',这正是我期待的。

我对 __loader__ 这个属性不是很确定,如果有什么问题请告诉我。

编辑:这个属性来源于 PEP 302:http://www.python.org/dev/peps/pep-0302/

从这个链接中有一些有趣的内容:

load_module() 方法在运行任何代码之前,有几个责任需要完成:

...

  • 它应该给模块添加一个 __loader__ 属性,并将其设置为加载器对象。这个主要是为了方便查看,但也可以用于特定于导入器的额外功能,比如获取与导入器相关的数据。

所以看起来在所有情况下它都应该能正常工作。

撰写回答