【问题标题】:How to prevent running the __main__ guard when using execfile?使用 execfile 时如何防止运行 __main__ 守卫?
【发布时间】:2014-05-17 17:30:55
【问题描述】:

BDFL 发布于 2003 年 an article about how to write a Python main function。他的例子是这样的:

import sys
import getopt

class Usage(Exception):
    def __init__(self, msg):
        self.msg = msg

def main(argv=None):
    if argv is None:
        argv = sys.argv
    try:
        try:
            opts, args = getopt.getopt(argv[1:], "h", ["help"])
        except getopt.error, msg:
             raise Usage(msg)
        # more code, unchanged
    except Usage, err:
        print >>sys.stderr, err.msg
        print >>sys.stderr, "for help use --help"
        return 2

if __name__ == "__main__":
    sys.exit(main())

将可选参数argv 改为main() 的原因是,“我们将main() 更改为可选的argv 参数,这允许我们从交互式Python 提示符调用它。”

他这样解释他的代码的最后一行:

现在sys.exit() 调用很烦人:当main() 调用sys.exit() 时, 您的交互式 Python 解释器将退出!补救办法是让 main() 的返回值指定退出状态。因此,代码在 最后变成了

if __name__ == "__main__":
    sys.exit(main())

并且在main() 中对sys.exit(n) 的调用都变为return n

但是,当我在 Spyder 控制台中运行 Guido 的代码时,它会杀死解释器。我在这里想念什么?我的意图是只 import 具有这种类型的 main() 模块,而不只是使用 execfilerunfile 执行它们吗?这不是我倾向于进行交互式开发的方式,尤其是考虑到它需要我记住在import fooreload(foo) 之间来回切换。

我知道我可以从getopt 中捕获SystemExit,或者尝试使用一些黑魔法来检测Python 是否以交互方式运行,但我认为这两者都不是BDFL 的意图。

【问题讨论】:

  • “我的意图是只导入具有这种 main() 类型的模块,而不是只使用 execfile 或 runfile 执行它们吗?”是的,我相信是的。为什么要使用execfilerunfile
  • 是的,你需要import它。当您执行/运行它时,__name____main__ 并且最后的 sys.exit 会运行。
  • @BrenBarn 问道,“为什么要使用 execfilerunfile?”假设我正在尝试编写一个中等复杂的函数。我将尝试在控制台中运行它几次,返回源文件并进行一些编辑,按 F5 执行该文件,然后再次从控制台对其进行测试。 import 在这种情况下效果不佳。这不是典型的吗?
  • @kuzzooroo:我认为不典型的是想要这样做想要以交互方式使用该功能但仍然具有相同的组合脚本可以作为主要运行。脚本导入一次后,可以使用reload 重新加载。
  • 最多,这是您的 IDE 的问题,当它运行的代码调用 sys.exit 时,它会关闭其嵌入式解释器。也许它应该在顶层默默地捕捉到那个异常,让你继续以交互方式做事。或者,您可以放弃程序返回值,只从您的 if __name__ == "__main__" 块中调用 main() 而无需 sys.exit 包装。

标签: python main exit


【解决方案1】:

您的选择是不使用 execfile 或将不同的 __name__ 值作为全局值传递:

execfile('test.py', {'__name__': 'test'})

默认是将文件作为脚本运行,这意味着__name__ 设置为__main__

您引用的文章仅适用于import

【讨论】:

    【解决方案2】:

    我在问题中简要提到的另一种处理方法是尝试检测您是否处于交互式上下文中。我不相信这可以便携地完成,但如果它对某人有帮助:

    if __name__ == "__main__":
        if 'PYTHONSTARTUP' in os.environ:
            try:
                main() # Or whatever you want to do here
            except SystemExit as se:
                logging.exception("")
        else:
            sys.exit(main())
    

    【讨论】:

      猜你喜欢
      • 2021-05-25
      • 1970-01-01
      • 1970-01-01
      • 2021-03-22
      • 1970-01-01
      • 2013-04-11
      • 1970-01-01
      • 1970-01-01
      • 2018-04-06
      相关资源
      最近更新 更多