-1

PROBLEM: Every time I run this python function in my monkeyrunner.py script, it opens a new background instance of (cmd, adb, and conhost). And so, in my automation script, if I have a loop that uses that 100 times, I'm going to see 100 of each cmd, adb, and conhost running in the background (I know this because I enter "ps" in powershell to get the list of processes.) The purpose of the function, if you're curious, is to look for logcat messages from the USB attached Android tablet, to see when processes are finished, so that the script knows when to command screen touches to move forward with automation testing.

action = "____"
waitTime = 1
def adb(logMessage, action):
    start = time.time()
    p = subprocess.Popen("adb logcat -v time", shell=True, cwd="C:\Users\<USERNAME>\AppData\Local\Android\sdk\platform-tools", stdout=subprocess.PIPE)
    for line in p.stdout:
        if logMessage in line:
            print("Found message!")
            break
            pass
        else:
            continue

QUESTION: How can I use "subprocess" to open adb WITHOUT opening a new instance each time? Is there a way to close the subprocess in the same function?

2 Answers2

0

2 things.

  1. adb logcat is a blocking call. It doesn't return unless you send it a SIGINT (ctrl +c). So inside a script you have to send it the "-d" flag. If you forget your script will keep waiting.
  2. you can wait for a subprocess to complete with p.wait()

Therefore you can try this

action = "____"
waitTime = 1
def adb(logMessage, action):
    start = time.time()
    p = subprocess.Popen("adb logcat -d -v time", shell=True, cwd="C:\Users\<USERNAME>\AppData\Local\Android\sdk\platform-tools", stdout=subprocess.PIPE)
    #p.wait()
    for line in p.stdout:
        if logMessage in line:
            print("Found message!")
            break
            pass
        else:
            continue

This will ensure that every adb session launched to look at logact terminates properly and its output is looked at only after it returns

EDIT: You are absolutely right, p.wait() isn't needed and is actually wrong! because the logcat writes more than 4kb to stdout in yourcase. You could try to use commuinicate instead to help with that

Srini
  • 1,619
  • 1
  • 19
  • 34
  • I tried the example you provided, but when I use it, the function appears to get stuck on the p.wait(). It never gets to the "for line in p.stdout:" loop, to look for the specified message. It just waits indefinitely. – JordanViaComputer Aug 07 '17 at 11:34
  • I appreciate the suggestion, but "communicate()" waits for a process to terminate. I need somethings, that works on Windows, that will terminate (or kill) the adb subprocess once it breaks out of the "if logMessage in line:" loop. The problem is, the python libs (modules) that Android gives you for MonkeyRunner is very limited, and things like "terminate()" or "kill()" do not exist in this version. – JordanViaComputer Aug 08 '17 at 17:56
  • but isn't that what the `-d` option does to logcat? you don't have to kill adb because it will exit itself after dumping the log – Srini Aug 08 '17 at 17:59
0

I figured it out. To prevent a new session of adb from opening in the background per each time this function is called, all I had to do is place the "p" variable outside the function.... like this...

p = subprocess.Popen("adb logcat -v time", shell=True, cwd="C:\Users\<USERNAME>\AppData\Local\Android\sdk\platform-tools", stdout=subprocess.PIPE)
action = "____"
waitTime = 1
def adb(logMessage, action):
    start = time.time()
    for line in p.stdout:
        if logMessage in line:
            print("Found message!")
            break
            pass
        else:
            continue

There is still the issue of a single adb session that opens and does not close after the script is run. So, now, instead of 180 sessions (or more) opening, there is a single one. If I find out how to close the session I will update this ticket.