python的setuptools支持`__name__ == "__main__"`的执行方式吗?

10 投票
1 回答
1924 浏览
提问于 2025-04-16 15:27

我刚开始学习用setuptools来打包,似乎推荐的方式是安装一个Python脚本时,要指定一个脚本名称,这个名称会调用一个函数,像这样:

setup(
    # ...
    entry_points = {
        "console_scripts": [
            "script_name": "project.main:main",
        ],
    }
)

这样做显然不再使用Python模块通常的可执行方式,也就是我上次查的时候(已经有一段时间了)是用 if __name__ == "__main__": do_stuff()。请问setuptools支持这种方式吗?还是说我应该换成定义一个主函数并在entry_points中指定它呢?

1 个回答

9

这里说的是:"script_name = project.main:do_stuff",这是用setuptools来做的。

setuptools会创建一个叫script_name的脚本,这个脚本会导入并运行project.main:do_stuff这个函数,而不是直接运行脚本本身。你应该再看看setuptools文档中的这一部分(如果你用的是Distribute,可以看这个链接),这样你能理解为什么是这样的。它创建的脚本里仍然包含if __name__ == "__main__"这段代码。所以,是的,这仍然是执行的标准方式。

这是用setuptools安装的easy_install的一个副本。

#!/usr/bin/python
# EASY-INSTALL-ENTRY-SCRIPT: 'distribute==0.6.14','console_scripts','easy_install'
__requires__ = 'distribute==0.6.14'
import sys
from pkg_resources import load_entry_point

if __name__ == '__main__':
    sys.exit(
        load_entry_point('distribute==0.6.14', 'console_scripts', 'easy_install')()
    )

我觉得最好是定义一个入口点和一个类似easy_install的脚本。这个脚本会导入并使用入口点,就像你在例子中展示的if __name__ == "__main__": do_stuff()。这样做对于调试和早期测试非常好,而且如果你使用distutils,就不需要添加或更改任何东西。你还可以有另一个应用程序来调用do_stuff(),这样就可以在不通过命令行运行的情况下访问你的应用,这正是setuptools所做的,distutils则是复制了这个脚本。

撰写回答