Search code examples
androidpythonshellsubprocessadb

subprocess.check_output fails to execute a command but the same works in windows


I am trying to connect two devices to my pc and run some commands on them using python and adb. when I run the command from the command prompt, it goes through fine, but when i put those in the python script, they give me errors. this is causing the errors all the time:

from subprocess import check_output, CalledProcessError
try:
    adb_ouput = check_output(["adb","devices","-l","|", "grep", "\"model\""])
    print adb_ouput
except CalledProcessError as e:
    print e

The error message I get is this:

Usage: adb devices [-l]
Command '['adb', 'devices', '-l', '|', 'grep', '"model"']' returned non-zero exit status 1

When I try the same code without the grep command, it works

adb_ouput = check_output(["adb","devices","-l"])

It gives me the right output.

When I try the same in windows command prompt, It works fine (I am replacing grep with FINDSTR because i'm using it in windows, and I have tried doing the same in the python script as well, with 'shell = True' and also without.)

eg:

adb devices -l | FINDSTR "model"

This gives me an ouptut without any problems. The output I get is

123ab6ef device product:xxxxxxxxx model:xxxxxxxxx device:xxxxxxxxx

bd00051a4 device product:yyyyyyyyyy model:yyyyyyyyyy device:yyyyyyyyy

I am trying to understand where I am going wrong here, but can't figure it out. So far I have checked the docs: https://docs.python.org/3/library/subprocess.html https://docs.python.org/3/library/subprocess.html#subprocess.CalledProcessError These just give me the error codes.

I have also looked at these answers: Python, adb and shell execution query I took some error checking from here and added to my code.

Python subprocess.check_output(args) fails, while args executed via Windows command line work OK python check_output fails with exit status 1 but Popen works for same command

I think i am close but just can't put my finger on it. Any help would be appreciated.


Solution

  • First

    adb_ouput = check_output(["adb","devices","-l","|", "grep", "\"model\""])
    

    certainly requires shell=True, but even with that it's not equivalent to

    adb devices -l | FINDSTR "model"
    

    When using check_output, you're passing "model" as grep argument literally but you should pass just model. "model" is not in your output (with quotes) so grep fails to find it, and returns exitcode 1 which is not really an error for grep but makes check_output trigger an exception because it expects 0.

    So I would to this as a quickfix:

    adb_ouput = check_output(["adb","devices","-l","|", "grep", "model"],shell=True)
    

    And as a longfix I'd perform the grep command directly with python.

    adb_output = check_output(["adb","devices","-l"])
    for l in adb_output.splitlines():
         if "model" in l:
             print(l)