有没有办法拯救某个命名空间下的所有异常?
例如,我想挽救所有 Errno::* 异常(Errno::ECONNRESET、Errno::ETIMEDOUT)。我可以继续在我的例外行中列出它们,但我想知道我是否可以做类似的事情。
begin
# my code
rescue Errno
# handle exception
end
上面的想法似乎不起作用,因此有类似的东西可以起作用吗?
有没有办法拯救某个命名空间下的所有异常?
例如,我想挽救所有 Errno::* 异常(Errno::ECONNRESET、Errno::ETIMEDOUT)。我可以继续在我的例外行中列出它们,但我想知道我是否可以做类似的事情。
begin
# my code
rescue Errno
# handle exception
end
上面的想法似乎不起作用,因此有类似的东西可以起作用吗?
动态创建模块
Errno
以将这些操作系统错误映射到 Ruby 类,每个错误号生成自己的SystemCallError
. 由于子类是在模块中创建的Errno
,它的名称将开始Errno::
。
所以你可以陷阱SystemCallError
然后做一个简单的名字检查:
rescue SystemCallError => e
raise e if(e.class.name.start_with?('Errno::'))
# do your thing...
end
这是另一个有趣的选择。可以适应你想要的。
粘贴最有趣的部分:
def match_message(regexp)
lambda{ |error| regexp === error.message }
end
begin
raise StandardError, "Error message about a socket."
rescue match_message(/socket/) => error
puts "Error #{error} matches /socket/; ignored."
end
请参阅 ruby 1.8.7 解决方案的原始站点。
事实证明 lambda 不接受我最近的 ruby 版本。似乎选项是使用 1.8.7 中的工作,但 IM 较慢(在所有比较中创建一个新类。所以我不建议使用它,甚至没有尝试过:
def exceptions_matching(&block)
Class.new do
def self.===(other)
@block.call(other)
end
end.tap do |c|
c.instance_variable_set(:@block, block)
end
end
begin
raise "FOOBAR: We're all doomed!"
rescue exceptions_matching { |e| e.message =~ /^FOOBAR/ }
puts "rescued!"
end
如果有人知道 ruby 何时删除了 lambda 支持,rescue
请发表评论。
Errno 下的所有类都是 SystemCallError 的子类。SystemCallError 的所有子类都是 Errno 下的类。2 套是相同的,所以只需救援 SystemCallError。这假设您没有使用添加到一个而不是另一个的外部库。
验证 2 个集合的身份(使用 active_support):
Errno.constants.map {|name|
Errno.const_get(name)
}.select{|const|
Class === const
}.uniq.map(&:to_s).sort ==
SystemCallError.subclasses.map(&:to_s).sort
这对我来说是回报true
。
因此,应用于您的示例:
begin
# my code
rescue SystemCallError
# handle exception
end
这是一个更通用的解决方案,如果您想拯救一些 Errno 类型而不是其他类型。
创建一个自定义模块以包含在我们要救援的所有错误类中
module MyErrnoModule; end
根据您的喜好自定义此数组,直至“每个”调用。
Errno.constants.map {|name|
Errno.const_get(name)
}.select{|const|
Class === const
}.uniq.each {|klass|
klass.class_eval {
include MyErrnoModule
}
}
测试:
begin
raise Errno::EPERM
rescue MyErrnoModule
p "rescued #{$!.inspect}"
end
测试结果:
"rescued #<Errno::EPERM: Operation not permitted>"
我猜这比需要检查异常名称的解决方案性能略好。