如何在MonkeyRunner中捕获SocketException? [英] How do I catch SocketExceptions in MonkeyRunner?

查看:186
本文介绍了如何在MonkeyRunner中捕获SocketException?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用MonkeyRunner时,经常会出现类似以下错误:

When using MonkeyRunner, every so often I get an error like:

120830 18:39:32.755:S [MainThread] [com.android.chimpchat.adb.AdbChimpDevice] Unable to get variable: display.density
120830 18:39:32.755:S [MainThread] [com.android.chimpchat.adb.AdbChimpDevice]java.net.SocketException: Connection reset

根据我所读的内容,有时adb连接断开,您需要重新连接.唯一的问题是,我无法捕获SocketException.我将这样包装代码:

From what I've read, sometimes the adb connection goes bad, and you need to reconnect. The only problem is, I'm not able to catch the SocketException. I'll wrap my code like so:

try:
    density = self.device.getProperty('display.density')
except:
    print 'This will never print.'

但是显然异常并未一直引发到调用者.我已经证实MonkeyRunner/jython可以按照我期望的方式捕获Java异常:

But the exception is apparently not raised all the way to the caller. I've verified that MonkeyRunner/jython can catch Java exceptions the way I'd expect:

>>> from java.io import FileInputStream
>>> def test_java_exceptions():
...     try:
...         FileInputStream('bad mojo')
...     except:
...         print 'Caught it!'
...
>>> test_java_exceptions()
Caught it!

如何处理这些套接字异常?

How can I deal with these socket exceptions?

推荐答案

以下是我最终使用的解决方法.可能遭受adb故障的任何功能都只需使用以下装饰器即可:

Below is the workaround I ended up using. Any function that can suffer from adb failures just needs to use the following decorator:

from subprocess import call, PIPE, Popen
from time import sleep

def check_connection(f):
    """
    adb is unstable and cannot be trusted.  When there's a problem, a
    SocketException will be thrown, but caught internally by MonkeyRunner
    and simply logged.  As a hacky solution, this checks if the stderr log 
    grows after f is called (a false positive isn't going to cause any harm).
    If so, the connection will be repaired and the decorated function/method
    will be called again.

    Make sure that stderr is redirected at the command line to the file
    specified by config.STDERR. Also, this decorator will only work for 
    functions/methods that take a Device object as the first argument.
    """
    def wrapper(*args, **kwargs):
        while True:
            cmd = "wc -l %s | awk '{print $1}'" % config.STDERR
            p = Popen(cmd, shell=True, stdout=PIPE)
            (line_count_pre, stderr) = p.communicate()
            line_count_pre = line_count_pre.strip()

            f(*args, **kwargs)

            p = Popen(cmd, shell=True, stdout=PIPE)
            (line_count_post, stderr) = p.communicate()
            line_count_post = line_count_post.strip()

            if line_count_pre == line_count_post:
                # the connection was fine
                break
            print 'Connection error. Restarting adb...'
            sleep(1)
            call('adb kill-server', shell=True)
            call('adb start-server', shell=True)
            args[0].connection = MonkeyRunner.waitForConnection()

    return wrapper

因为这可能会创建一个新连接,所以您需要将当前连接包装在Device对象中,以便可以对其进行更改.这是我的Device类(大多数类是为了方便起见,唯一需要的是connection成员:

Because this may create a new connection, you need to wrap your current connection in a Device object so that it can be changed. Here's my Device class (most of the class is for convenience, the only thing that's necessary is the connection member:

class Device:
    def __init__(self):
        self.connection = MonkeyRunner.waitForConnection()
        self.width = int(self.connection.getProperty('display.width'))
        self.height = int(self.connection.getProperty('display.height'))
        self.model = self.connection.getProperty('build.model')

    def touch(self, x, y, press=MonkeyDevice.DOWN_AND_UP):
        self.connection.touch(x, y, press)

有关如何使用装饰器的示例:

An example on how to use the decorator:

@check_connection
def screenshot(device, filename):
    screen = device.connection.takeSnapshot()
    screen.writeToFile(filename + '.png', 'png')

这篇关于如何在MonkeyRunner中捕获SocketException?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆