如何拯救Psych Yaml例外?

时间:2017-01-31 09:28:54

标签: ruby yaml

这实际上是3部分问题:

  1. Psych抛出的所有异常是什么?
  2. 当文档没有列出时,你怎么知道它们是哪些?
  3. 用于捕获所有可能的YAML.load_file异常的示例代码?
  4. 我不会要求3号,但这个问题表明我会遇到一些奇怪的问题: Can't rescue YAML.load exception

    基于这个问题 How to know what exceptions to rescue

    我得到了:

    Psych::Exception
          Psych::BadAlias
          Psych::DisallowedClass
          Psych::SyntaxError
    

    但是当我试图抓住代码仍然失败时

    irb(main):002:0> begin
    irb(main):003:1* YAML.load_file('test_file_does_not_exist')
    irb(main):004:1> rescue Psych::Exception
    irb(main):005:1> puts $!.message
    irb(main):006:1> end
    Errno::ENOENT: No such file or directory @ rb_sysopen - test
        from /home/marko/.gem/ruby/2.3.1/gems/psych-2.1.0/lib/psych.rb:474:in `initialize'
        from /home/marko/.gem/ruby/2.3.1/gems/psych-2.1.0/lib/psych.rb:474:in `open'
        from /home/marko/.gem/ruby/2.3.1/gems/psych-2.1.0/lib/psych.rb:474:in `load_file'
        from (irb):3
        from /home/marko/.rubies/ruby-2.3.1/bin/irb:11:in `<main>'
    

    我正在寻找方法来捕捉所有这些废话。无论失败的原因是什么,我都想抓住它并在它回到主要的异常处理代码之前显示一条消息。

    微软,我不是特别喜欢,它显示了他们写过的每个课程的所有例外情况。例: https://msdn.microsoft.com/en-us/library/b9skfh7s(v=vs.110).aspx

1 个答案:

答案 0 :(得分:2)

心理异常

检查的一种方法是:

exceptions_before = ObjectSpace.each_object(Class).select{|klass| klass < Exception}
require 'yaml'
exceptions_after  = ObjectSpace.each_object(Class).select{|klass| klass < Exception}

它可能会错过动态生成的异常。不过,这是2和他们的祖先之间的区别:

(exceptions_after - exceptions_before).each do |yaml_exception|
  p yaml_exception.ancestors
end

# [Psych::SyntaxError, Psych::Exception, RuntimeError, StandardError, Exception, Object, Kernel, BasicObject]
# [Psych::DisallowedClass, Psych::Exception, RuntimeError, StandardError, Exception, Object, Kernel, BasicObject]
# [Psych::BadAlias, Psych::Exception, RuntimeError, StandardError, Exception, Object, Kernel, BasicObject]
# [Psych::Exception, RuntimeError, StandardError, Exception, Object, Kernel, BasicObject]
# [StringScanner::Error, StandardError, Exception, Object, Kernel, BasicObject]

似乎Psych::ExceptionStringScanner::Error涵盖Psych引发的所有例外情况。

其他例外

任何地方都可能出错。不过,最常见的例外是:

Errno::ENOENT

如果找不到您的.yml。您可以抢救异常,也可以在阅读yaml文件之前检查File.exist?

恕我直言,你不应该试图拯救每一个例外。

即使看起来你正在寻找rescue => e甚至是rescue Exception => e,它仍然是not a good idea