问题
I want a class that will load and save settings in yaml file, and displays an error if something happens. I must catch exceptions and I must know what to catch. There is no guarantee what exception will be raised; user might press CTRL+C or memory may run out, but YAML.load_file can raise only a limited number of exceptions. There is nowhere listed what exceptions a function YAML.load_file might raise.
How can I catch only them when I don't know what those exceptions are?
This question has been asked, but there is no real answer:
- How to know what exceptions to rescue? Answer is about exceptions in general
- How to deal with not knowing what exceptions can be raised by a library method in Ruby?
- Ruby How to know what to rescue?
- Where to find (or how to read) ruby documentation?
- Documentation for Ruby exceptions
回答1:
Sometimes you just don't know which kind of exception can be thrown, for that the generic rescue catching exists.
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
回答2:
How can I catch only them when I don't know what those exceptions are?
What are you going to do when you catch them, I wonder? It makes little sense to catch exceptions for the sake of catching. Swallowing exceptions is especially bad practice.
My rule of thumb is: catch only those I can recover from (this implies already knowing what they are). Let the rest bubble up and crash the program or possibly be catched in one of outer scopes (which will know how to recover from this concrete one).
How to discover currently loaded exception classes
This almost 10 year old code snippet still works today:
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
Run it in the rails console and you'll see a lot of exception classes. :)
回答3:
The source code is the documentation.
-- Matz
来源:https://stackoverflow.com/questions/34443407/how-to-know-what-exceptions-to-rescue