【问题标题】:Emergency exit in Python without goto没有 goto 的 Python 中的紧急出口
【发布时间】:2012-01-26 06:11:07
【问题描述】:

在 C 语言中,当发生无法优雅处理的异常时,我经常使用 goto 跳出函数的中间并解开我在函数中所做的任何事情;例如关闭文件描述符,释放不会使用的分配内存,例如

error3:
    for(j=0; j<i; j++) {
        nameDelete(names[j]);
    }
error:2
    free(names);
error1:
    close(fd);
error0:
    exit(-1);

在我打开 fd 之前的代码早期,我会在 error0: 处跳出,然后在 error1: 处跳出,依此类推,以获取资源。

Python 没有这种结构。相反,我正在查看一个又一个条件,我必须一遍又一遍地放入适当的代码,如果我在某个时候更改函数以获取资源,我需要确保它下面的所有过早退出正确地处理该资源在某一时刻。

我不拘泥于 goto 语法(我读过 Dijkstra),但是我想知道 Python 中这种操作是否有一个通用模式。简而言之对 Python 的(快速)调查并没有太大帮助。

[编辑]

我要避免的是

try:
    foo1
except: 
    bar0
try: 
    foo2
except: 
    bar0
try: 
    foo3
except: 
    bar1
try:
    foo4
except:
    bar2

其中 bar2 包括 bar2 中的所有内容,其中包括 bar0 中的所有内容。我承认我在 bar# 中所做的大部分工作都可能由 GC 处理,但我更喜欢迂腐,尤其是在我重构代码之前移植代码(这就是我正在做的事情)时。

【问题讨论】:

  • 你用的是什么 Python 教程?所有这些都应涵盖 try:except 语句。另外,with 语句也做了一些这样的事情。你用的是什么教程?它是否涵盖这些陈述?
  • 哎呀——太可怕了,请停下来。 (我说的是你的 C 编码“风格”)
  • @KevinDTimm:它实际上很常见,并且在 linux 内核中被广泛使用。您甚至可能会争辩说,这是在 C 中进行清理的唯一合理且快速的方法。
  • 如果你还是要退出进程,是不是不需要进行任何清理? Related: "大楼要拆了,不用扫地、倒垃圾桶、擦白板。"
  • “关闭文件描述符”可能不适用;它通常是自动处理的。 “空闲分配的内存”不适用。您能否提供任何与 Python 相关的具体内容?

标签: python goto


【解决方案1】:

Python 为此使用异常系统:

raise Exception("ERROR")

这将继续“解开”并清理堆栈,直到异常被异常处理程序捕获。如果异常没有被捕获,程序会停止,打印异常并退出。

the official Python tutorial 中阅读有关异常的更多信息。

此外,您还描述了资源的使用。这是通过两种模式完成的:

  • 初始化和清理,资源在初始化时分配,在释放时释放(方法__init____del__
  • with 声明,(方法__enter____exit__

如果发生异常,两种模式都会正确清理。

【讨论】:

  • 我不太担心堆栈,而是担心函数(方法)中发生的事情。在函数中,我可以使用 try: 和 except: 语法,但这仍然给我留下了同样的问题,据我所知,这就是我必须解开我在函数中所做的事情。我要避免的是看起来像'if condition: blah if condition: blah if condition: blah' 或'try: foo except: bar try: foo2 except: bar try: foo3 except: bar'
  • +1。 @迈克尔康伦。另请阅读有关 RAII 的信息,这是背后的想法。只要所有状态都由对象持有,您提到的废话条件就不会发生。 en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization
  • @MichaelConlen:“我必须弄清楚我在函数中所做的事情”?这是什么意思?请更新这个问题,具体说明您可能认为需要解决的问题。 Python 已经有了垃圾收集和上下文管理器。你认为你需要做什么?
【解决方案2】:

我不确定我是否完全理解您的需求,但听起来您可以使用try ... except ... finally

在此处阅读有关异常和异常处理的更多信息:http://docs.python.org/tutorial/errors.html

【讨论】:

    【解决方案3】:

    如果您需要处理错误,请使用异常。来自官方 Python 手册的示例:

    try:
        f = open('myfile.txt')
        s = f.readline()
        i = int(s.strip())
    except IOError as (errno, strerror):
        print "I/O error({0}): {1}".format(errno, strerror)
    except ValueError:
        print "Could not convert data to an integer."
    except:
        print "Unexpected error:", sys.exc_info()[0]
        raise
    

    顺便说一句,您可以在需要时提出自己的自定义异常。

    【讨论】:

      【解决方案4】:

      除了例外,with 语句通常特别与文件描述符一起使用。

      http://effbot.org/zone/python-with-statement.htm

      http://docs.python.org/reference/compound_stmts.html#the-with-statement

      仅供参考,尽管这是“不好的做法”,但文件对象在被 GC 处理后就会立即关闭,只要您没有其他对它们的引用,这种情况就会在它们超出范围时发生。所以这实际上不会打开文件:

      def _readfile():
          f = open("path")
          return f.read()
      

      但你肯定会因此受到评判,如果那是你的事:)

      【讨论】:

        猜你喜欢
        • 2021-10-13
        • 2018-09-11
        • 2015-06-13
        • 2013-05-05
        • 2023-04-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多