如何判断Python脚本是作为模块导入还是作为脚本运行的?
这个问题其实很简单,但在搜索时没有找到答案。怎么才能在一个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
你就可以让这个文件既可以作为脚本使用,也可以作为可导入的模块,因为只有当这个模块作为“主”文件被执行时,解析命令行的代码才会运行。