Python 从函数中退出()是一种糟糕的形式吗?

Python 从函数中退出()是一种糟糕的形式吗?,python,function,Python,Function,从函数中退出()是不是很糟糕 def respond_OK(): sys.stdout.write('action=OK\n\n') sys.stdout.flush() # redundant when followed by exit() sys.exit(0) 而不是设置退出代码并从\uuuu main\uuu名称空间退出 def respond_OK(): global exit_status sys.stdout.write('action=O

从函数中退出()是不是很糟糕

def respond_OK():
    sys.stdout.write('action=OK\n\n')
    sys.stdout.flush() # redundant when followed by exit()
    sys.exit(0)
而不是设置退出代码并从
\uuuu main\uuu
名称空间退出

def respond_OK():
    global exit_status
    sys.stdout.write('action=OK\n\n')
    sys.stdout.flush()
    exit_status = 0

sys.exit(exit_status)

从功能的角度来看,差异可以忽略不计,只是想知道在形式上的共识是什么。如果您在其他人的代码中找到了Previor,您会看两次吗?

它在功能上没有区别,但它可能会使您的代码更难遵循,除非您采取适当的步骤,例如注释来自主命名空间的每个调用,这可能导致退出

更新:注意@mgilson的回答是捕获异常的效果[有可能捕获
system.exit
引发的异常,从而阻止退出]。这样可能会使代码更加混乱


更新2:Note@sapht建议使用异常来协调退出。这是一个很好的建议,如果你真的想做一个非本地退出。比设置全局调用要好得多。

它在功能上没有什么区别,但可能会使代码更难理解,除非您采取适当的步骤,例如注释来自主命名空间的每个调用,这可能导致退出

更新:注意@mgilson的回答是捕获异常的效果[有可能捕获
system.exit
引发的异常,从而阻止退出]。这样可能会使代码更加混乱


更新2:Note@sapht建议使用异常来协调退出。这是一个很好的建议,如果你真的想做一个非本地退出。比设置全局异常要好得多。

我更希望看到从主入口点引发和处理异常,其类型转换为退出代码。在python中,子类化异常非常简单,几乎很有趣


正如本答案评论中所述:使用sys.exit还意味着终止点需要知道实际的状态代码,而不是它遇到的错误类型。当然,这可以通过一组常数来解决。不过,使用异常还有其他好处:如果一个方法失败,您可以尝试另一个方法,而无需重新输入,或者打印一些事后调试信息。

我更希望看到从主入口点引发并处理异常,其类型转换为退出代码。在python中,子类化异常非常简单,几乎很有趣


正如本答案评论中所述:使用sys.exit还意味着终止点需要知道实际的状态代码,而不是它遇到的错误类型。当然,这可以通过一组常数来解决。不过,使用异常还有其他好处:如果一种方法失败,您可以尝试另一种方法,而无需重新输入,或者打印一些事后调试信息。

在某些情况下,它是合理的惯用方法

如果用户向您提供了错误的命令行参数,请改为:

def usage(arg0):
  print ... % (arg0,)
  return 2

if __name__ == '__main__':
  if ...:
    sys.exit(usage(sys.argv[0]))
你经常会看到:

def usage():
  print ... % (sys.argv[0],)
  sys.exit(2)

if __name__ == '__main__':
  if ...:
    usage()
我能想到的另一种常见情况是,初始化某些库(通过ctypes或低级C扩展模块)时意外失败,使您处于无法推理的状态,因此您只想尽快退出(例如,减少出现故障或打印垃圾的机会),例如:

if libfoo.initialize() != 0:
  sys.exit(1)

有些人可能会反对这样做,因为
sys.exit
实际上并没有尽快跳出解释器(它抛出并捕获异常),所以这是一种错误的安全感。但是你仍然可以经常看到它。

在一些情况下,它相当地道

如果用户向您提供了错误的命令行参数,请改为:

def usage(arg0):
  print ... % (arg0,)
  return 2

if __name__ == '__main__':
  if ...:
    sys.exit(usage(sys.argv[0]))
你经常会看到:

def usage():
  print ... % (sys.argv[0],)
  sys.exit(2)

if __name__ == '__main__':
  if ...:
    usage()
我能想到的另一种常见情况是,初始化某些库(通过ctypes或低级C扩展模块)时意外失败,使您处于无法推理的状态,因此您只想尽快退出(例如,减少出现故障或打印垃圾的机会),例如:

if libfoo.initialize() != 0:
  sys.exit(1)

有些人可能会反对这样做,因为
sys.exit
实际上并没有尽快跳出解释器(它抛出并捕获异常),所以这是一种错误的安全感。但你仍然经常看到它。

这是一个相当主观的问题。在一个足够小的应用程序中(例如,简单的脚本),我可能不会在意。然而,如果把它放在一个大型项目中,我会担心到处都有出口。当然,这只是问“什么是大项目”的问题?一个主观的问题值得另一个,我想:PI不明白为什么从任何地方调用
exit()
和调用任何其他函数都是不好的形式。不好的是:
globals()['exit\u status']=0
Eww。@FogleBird更喜欢这样吗?:不恰当的主观问题。在一个足够小的应用程序中(例如,简单的脚本),我可能不会在意。然而,如果把它放在一个大型项目中,我会担心到处都有出口。当然,这只是问“什么是大项目”的问题?一个主观的问题值得另一个,我想:PI不明白为什么从任何地方调用
exit()
和调用任何其他函数都是不好的形式。不好的是:
globals()['exit\u status']=0
Eww。@FogleBird更喜欢这样吗?:p这正是
sys.exit
所做的。它提出了哪些可以抓住或不抓住。好的方面是,如果您选择让解释器在该点退出,它不会打印出难看的回溯。是的,但是终止点需要知道实际的状态代码,而不是它遇到的错误类型。当然,这可以通过一组常数来解决。不过,使用异常还有其他好处:如果一个方法失败,您可以尝试另一个方法,而无需重新输入,或者打印一些事后调试信息。@sapht将其添加到您的ans中