首页 > 解决方案 > 在 Python 中使用入口点时区分导入的包和在 CLI 中运行的包

问题描述

我有一个最常用作 CLI 工具的 python 包,但有时我出于自己的目的将它作为库运行。(例如把它变成一个网络应用程序或进行单元测试)

例如,sys.exit(1)当用作 CLI 命令时,我想给最终用户一个关于异常的很好的错误消息,raise但当它用作导入库时,我想给最终用户一个很好的错误消息。

entry_points在我的setup.py

entry_points={
        'console_scripts': [
            'jello=jello.cli:main'
        ]
    }

这很好用,但我无法轻易区分包是在 CLI 上运行还是导入的,因为__name__总是jello.cli. 这是因为入口点基本上是照常导入包。

我尝试创建一个__main__.py文件并将我的入口点指向那里,但这似乎没有什么不同。

我正在考虑检查sys.argv[0]我的程序名称是否存在,但这似乎是一个脆弱的黑客。(以防用户为命令或其他东西起别名)还有其他想法还是我做错了?现在我一直在as_lib向我的函数传递一个参数,因此它们的行为会根据它们是作为模块加载还是从 CLI 运行而有所不同,但我想摆脱这种情况。

标签: pythonentry-point

解决方案


我相信你想要的在 Python 中被称为“主要守卫”。该模块在任何给定时间都知道它的名称。如果模块是从 CLI 执行的,则其名称为__main__. 因此,您可以做的是将您想要的所有功能放在模块级别的某个函数中,然后您可以在“主要守卫”中以不同于您将其作为库调用的方式调用它。这是“主要后卫”的样子:

def myfunc(thing, stuff):
   if not stuff:
      raise MyExc

if __name__ == '__main__':
    try:
       myfunc(x, y)
    except MyExc:
       sys.exit(1)

在这里,只有在模块作为脚本从命令行执行时,sys.exit 才会在出错时被调用。


推荐阅读