如何判断Python脚本是作为模块导入还是作为脚本运行的?

38 投票
2 回答
13424 浏览
提问于 2025-04-15 14:07

这个问题其实很简单,但在搜索时没有找到答案。怎么才能在一个Python脚本中判断这个脚本是作为模块被导入,还是直接运行的呢?在Python中,这两者有什么区别吗?

我的问题是,我只想在脚本被直接运行时评估命令行参数,而如果这个模块只是被导入到另一个脚本中,就不想评估这些参数。(我希望能把一个脚本既当作库用,也当作程序用。)我担心最常见的做法是把库和一个使用它的第二个脚本分开,但我想要一个更简单的选择,适合小工具或小库。

2 个回答

5

正如 @bobince 所指出的:

如果你是通过 python -m somemodule 命令调用的模块,你也会是 __main__

假设你有一个 Python 文件 bar.py 和一个空的 __init__.py,它们都在一个叫 foo 的文件夹里:

$ tree
.
└── foo
    ├── __init__.py
    └── bar.py

$ cat foo/__init__.py

下面的 Python 代码块是 foo/bar.py 的内容。

使用 __name__(不工作)

print('Code executed as a %s' % 'script' if __name__ == '__main__' else 'module')

这将产生:

$ python foo/bar.py
Code executed as a script

$ python -m foo.bar
Code executed as a script

解决方案 1:使用 vars()sys.modules

import sys
mod_name = vars(sys.modules[__name__])['__package__']
print('Code executed as a ' + ('module named %s' % mod_name if mod_name else 'script'))

这将产生:

$ python foo/bar.py
Code executed as a module named foo

$ python -m foo.bar
Code executed as a script

解决方案 2:在模块导入时使用 try-except 块

import sys
try:
    import foo
    print('Code executed as a module')
except ImportError:
    print('Code executed as a script')
    # Code will fail here, but you can still print a comprehensive error message before exiting:
    print('Usage: python -m foo.bar')
    sys.exit()

这将产生:

$ python foo/bar.py
Code executed as a module

$ python -m foo.bar
Code executed as a script
Usage: python -m foo.bar
53

来自Python的文档

当你用下面的命令运行一个Python模块时:

python fibo.py

模块里的代码会被执行,就像你导入它一样,但这时__name__的值会被设置为"__main__"。这意味着,如果你在模块的最后加上这段代码:

if __name__ == '__main__':
    # Running as a script

你就可以让这个文件既可以作为脚本使用,也可以作为可导入的模块,因为只有当这个模块作为“主”文件被执行时,解析命令行的代码才会运行。

撰写回答