关于异常处理:ruby不会超越第一个救援代码?

ruby does not look beyond the first rescue code?

根据我对文档的理解,这种一般方法应该有效:

1
2
3
4
5
6
7
8
9
10
11
12
begin
 try1
rescue
 try2
rescue
 try3
.
.
.
rescue
 puts"Everybody failed, sorry man!"
end

然而,每当我尝试打开Watir-Webdriver浏览器时,它似乎永远不会超过第二个$ browser = Watir :: Browser.new,结束第189行中的脚本连接被拒绝 - 连接(2)(Errno :: ECONNREFUSED)

Code.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
begin
 $browser = Watir::Browser.new(:firefox, :profile =>"botmode") # **line 186**

rescue
 $browser = Watir::Browser.new(:remote, :url =>"http://127.0.0.1:4444/wd/hub", :desired_capabilities => :firefox)   # **line 189**

rescue  # local selenium htmlunit
  puts __LINE__.to_s +": #{$!}"    
#  $browser = Watir::Browser.new(:remote, :url =>"http://127.0.0.1:4444/wd/hub", :desired_capabilities => :htmlunit)  # but needs Javascript for AJAX support...
  $browser = Watir::Browser.new(:remote, :url =>"http://127.0.0.1:4444/wd/hub", :desired_capabilities => Selenium::WebDriver::Remote::Capabilities.htmlunit(:javascript_enabled => true, :cssSelectorsEnabled=>true, :nativeEvents=>false) )

rescue # Try to use VentanaPC if still failing..  
 $browser = Watir::Browser.new(:remote, :url =>"http://5.19.111.226:4444/wd/hub", :desired_capabilities => :firefox)  

rescue  # no browser left to failover to
  puts __LINE__.to_s +": #{[email protected]_s}"
end

# ruby -v
ruby 1.9.2p290 (2011-07-09 revision 32553) [i686-linux]

为了使第186行失败,我故意将DISPLAY =:88提前设置为不存在的Xserver,所以这个错误没问题:186:无法在60秒内获得稳定的firefox连接(127.0.0.1:7055)

我在哪里错了,或者有更好的方法吗? 这对Selenium或Watir来说是特别的吗?


您的假设是错误的,这不符合您的预期:

1
2
3
4
5
6
7
8
9
10
11
12
13
irb(main):062:0> begin
irb(main):063:1*   raise StandardError
irb(main):064:1> rescue
irb(main):065:1>   puts"test1"
irb(main):066:1>   raise StandardError
irb(main):067:1> rescue
irb(main):068:1>   puts"test2"
irb(main):069:1> end
test1
StandardError: StandardError
    from (irb):66:in `rescue in irb_binding'
    from (irb):62
    from /usr/bin/irb:12:in `
<main>'

test2未打印。 多个rescue用于不同的异常类型,您无法捕获其他rescue块中的错误。 您可以使用嵌套的begin/rescue块,但这种情况看起来很复杂,可以使用更通用的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
methods = [
  lambda { Watir::Browser.new(:firefox, :profile =>"botmode") },
  lambda { Watir::Browser.new(:remote, :url =>"http://127.0.0.1:4444/wd/hub", :desired_capabilities => :firefox) },
  lambda { Watir::Browser.new(:remote, :url =>"http://127.0.0.1:4444/wd/hub", :desired_capabilities => Selenium::WebDriver::Remote::Capabilities.htmlunit(:javascript_enabled => true, :cssSelectorsEnabled=>true, :nativeEvents=>false) ) },
  lambda { Watir::Browser.new(:remote, :url =>"http://5.19.111.226:4444/wd/hub", :desired_capabilities => :firefox) },
]

def get_first_successful(methods)
  methods.each do |m|
    begin
      return m.call
    rescue
    end
  end
  nil
end

$browser = get_first_successful(methods)

这将选择第一个没有失败的方法。 但是,如果第二个失败,我不知道最后一个如何成功,你可能会在这里重新考虑你的选择。


多次救援用于从不同的异常类型中拯救; 你拥有的是一个带有一堆不合格救援的单块,所以只有一个会触发。 您希望嵌套开始/救援/结束,或完全不同的方法。


第一个rescue将捕获任何StandardError。 其他人也是如此,但由于这些错误已经被第一个rescue捕获,他们将永远不会有机会遇到任何StandardError