【问题标题】:How to know what exceptions to rescue如何知道要抢救哪些异常
【发布时间】:2015-12-23 20:42:52
【问题描述】:

我想要一个可以在 yaml 文件中加载和保存设置的类,如果出现问题会显示错误。我必须捕捉异常,我必须知道要捕捉什么。无法保证会引发什么异常;用户可能按下 CTRL+C 或内存可能耗尽,但 YAML.load_file 只能引发有限数量的异常。没有任何地方列出函数 YAML.load_file 可能引发的异常。

当我不知道这些异常是什么时,如何只捕获它们?

有人问过这个问题,但没有真正的答案:

【问题讨论】:

  • 在任何没有检查异常的语言中你都知道。甚至是那些未经检查的人。阅读文档。阅读测试。阅读代码。你看到人们多次问这个问题,但没有得到灵丹妙药,但你决定再问一次。你怎么知道如何使用任何 API?
  • 我如何找到ruby-doc.org/core-2.0.0/IO.html#method-i-write 的源代码或测试我知道“点击切换源代码”按钮,但它没有显示任何有用的信息。

标签: ruby exception


【解决方案1】:

有时您只是不知道可以抛出哪种异常,因为存在通用的rescue 捕获。

begin
    do_something
rescue KnownException
    treat_exception
# generic exception 
rescue Exception => e
    # you don't know which exception has been raised but all info is in e
    print "Ups I don't know this Exception:#{e.class} error: #{e.message}"
    raise
end

【讨论】:

  • 你得到 -1 拯救异常 :)
  • 好吧,你不要再加注。
  • 我不认为这是一个糟糕的答案。如果您完全不确定,那么这至少会向您显示正在提高的那个,以便您可以相应地处理。
  • 我认为这是一个糟糕的过程。我不想吞下例外。我目前正在做的是将代码推入极端情况并使程序失败,然后读取抛出的异常名称。但我确信我在这种方式下遗漏了一些东西,必须有一种更有效的方式。
【解决方案2】:

当我不知道这些异常是什么时,如何只捕获它们?

我想知道,当你抓住它们时你会怎么做?为了捕捉而捕捉异常是没有意义的。吞下异常是特别糟糕的做法。

我的经验法则是:只捕获那些我可以从中恢复的(这意味着已经知道它们是什么)。让其余部分冒泡并使程序崩溃,或者可能被捕获在外部范围之一(它将知道如何从这个具体的范围中恢复)。

如何发现当前加载的异常类

This almost 10 year old code snippet 今天仍然有效:

exceptions = []
tree = {}
ObjectSpace.each_object(Class) do |cls|
  next unless cls.ancestors.include? Exception
  next if exceptions.include? cls
  exceptions << cls
  cls.ancestors.delete_if {|e| [Object, Kernel].include? e }.reverse.inject(tree) {|memo,cls| memo[cls] ||= {}}
end

indent = 0
tree_printer = Proc.new do |t|
  t.keys.sort { |c1,c2| c1.name <=> c2.name }.each do |k|
    space = (' ' * indent); space ||= ''
    puts space + k.to_s
    indent += 2; tree_printer.call t[k]; indent -= 2
  end
end
tree_printer.call tree

在 rails 控制台运行它,你会看到很多异常类。 :)

【讨论】:

  • 从异常中恢复并不意味着知道它们是什么。如果我知道这些异常的名称,我知道如何从“您无法写入此文件夹”或“文件名无效”中恢复。而且它没有在我看过的任何地方列出。
  • @MarkoAvlijaš:查看这篇文章:blog.nicksieger.com/articles/2006/09/06/…。如果您在 Rails 应用程序中运行此代码,您将获得更大的异常树。这是你的清单。
  • 特别是“没有这样的文件”错误被称为Errno::ENOENT
  • 谢谢,这很有用。知道如何将此代码应用于(其他人的)班级吗?我现在能想到的就是在将类和输出结果包含到文件之前运行它,然后运行它并进行比较。这样,我将捕获独特的异常,但会错过标准 ruby​​ 代码正在使用的异常。
  • 您想弄清楚并从中创建答案吗?这个问题被问了很多,但没有给出真正的答案。
【解决方案3】:

源代码是文档。

-- 马茨

【讨论】:

  • 在哪里可以找到它?在 ruby​​-doc.org 上的代码是无用的 - 它是 C 和部分的。看看 IO#write。 ruby-doc.org/core-2.0.0/IO.html#method-i-write
  • @MarkoAvlijaš 你不是在找YAML.load_file吗?
  • 是加载和保存设置。对于保存设置,我使用 File.write / IO.write
  • @MarkoAvlijaš:恐怕您必须阅读大量 ruby​​ 代码库才能了解从核心和标准库中抛出了哪些异常。 This file 将为 grepping 提供关键字(C 函数名称)。作为替代方案,您可以阅读 rubinius 代码,更不用说那里的 C :)
猜你喜欢
  • 2012-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-12
  • 1970-01-01
  • 1970-01-01
  • 2015-07-03
  • 1970-01-01
相关资源
最近更新 更多