2012-08-31 14 views
6

MonkeyRunner उपयोग करते समय, हर बार मैं की तरह एक त्रुटि प्राप्त:मैं MonkeyRunner में सॉकेट अपवाद कैसे पकड़ूं?

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 

मैं क्या पढ़ा है से, कभी कभी एडीबी कनेक्शन बुरा हो जाता है, और आप फिर से कनेक्ट करने की जरूरत है। एकमात्र समस्या यह है कि, मैं SocketException को पकड़ने में सक्षम नहीं हूं। मैं अपना कोड इस प्रकार लपेटूंगा:

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

लेकिन अपवाद स्पष्ट रूप से कॉलर के लिए सभी तरह से उठाया नहीं गया है। मैं सत्यापित किया है कि MonkeyRunner/Jython जावा अपवाद तरह से मैं उम्मीद थी पकड़ कर सकते हैं:

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

मैं इन सॉकेट अपवादों के साथ कैसे सौदा कर सकते हैं?

उत्तर

2

नीचे वर्कअराउंड है जिसका उपयोग मैंने समाप्त किया था। किसी भी समारोह है कि एशियाई विकास बैंक विफलताओं से ग्रस्त हो सकते बस निम्नलिखित डेकोरेटर का उपयोग करने की जरूरत है:

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 

क्योंकि यह एक नया कनेक्शन बना सकते हैं, तो आप एक डिवाइस वस्तु में अपने वर्तमान कनेक्शन रैप करने के लिए इतना है कि यह बदला जा सकता है की जरूरत है। यहाँ मेरी डिवाइस वर्ग है (वर्ग का सबसे सुविधा के लिए है, केवल एक चीज आवश्यक है कि connection सदस्य है:

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) 

कैसे डेकोरेटर का उपयोग करने पर एक उदाहरण:

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

ठीक है, मैं ने कहा है कि के कारण नहीं है है: परिशिष्ट के रूप में, मैं भी जावा त्रुटि देखें करने के लिए एक रास्ता मिल गया एक 'adb' अस्थिरता लेकिन MonkeyRuner/Chimpchat वाले। [एंड्रॉइड व्यूक्लिएंट/कुलेब्रा] (https://github.com/dtmilano/AndroidViewClient) एक 'adbclient', एक पायथन मॉड्यूल का उपयोग करता है जो' adb' के साथ सभी संवाद को समाहित करता है और यह बहुत स्थिर है। –

6

आपको लगता है कि मिल जाएगा इस समस्या को हल करने के लिए एक अच्छा तरीका है कि हर बार जब आप अजीब MonkeyRunner शुरू क्योंकि डिवाइस पर monkey --port 12345 आदेश नहीं रोका जाता है जब अपनी स्क्रिप्ट बंद हो जाता है त्रुटि। यह बंदर में एक बग है।

बंदर जबमार रहा है 210 आपकी स्क्रिप्ट पर भेजा गया है (जब आप ctrl+c)। दूसरे शब्दों में: $ killall com.android.commands.monkey

त्वरित तरीका यह करने के लिए:

from sys, signal 
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice 

device = None 

def execute(): 
    device = MonkeyRunner.waitForConnection() 
    # your code 

def exitGracefully(self, signum, frame): 
    signal.signal(signal.SIGINT, signal.getsignal(signal.SIGINT)) 
    device.shell('killall com.android.commands.monkey') 
    sys.exit(1) 

if __name__ == '__main__' 
    signal.signal(signal.SIGINT, exitGracefully) 
    execute() 

संपादित करें: Monkey Runner throwing socket exception broken pipe on touuch

संबंधित मुद्दे