7

I am trying to store the output of a cmd command as a variable in python. To achieve this i am using os.system() but os.system() just runs the process,it doesn't capture the output.

import os


PlatformName = os.system("adb shell getprop | grep -e 'bt.name'")
DeviceName = os.system("adb shell getprop | grep -e '.product.brand'")
DeviceID = os.system("adb shell getprop | grep -e 'serialno'")
Version = os.system("adb shell getprop | grep -e 'version.release'")

print(PlatformName)
print(DeviceName)
print(DeviceID)
print(Version)

Then i tried to use the subprocess module.

import subprocess
import os


PlatformName = subprocess.check_output(["adb shell getprop | grep -e 'bt.name'"])
DeviceName = subprocess.check_output(["adb shell getprop | grep -e '.product.brand'"])
DeviceID = subprocess.check_output(["adb shell getprop | grep -e 'serialno'"])
Version = subprocess.check_output(["adb shell getprop | grep -e 'version.release'"])

print(PlatformName)
print(DeviceName)
print(DeviceID)
print(Version)

I am getting the following error

FileNotFoundError: [WinError 2] The system cannot find the file specified

How can I store the output of the command as a variable?

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
AutoTester213
  • 2,714
  • 2
  • 24
  • 48
  • I think you should just separate each piece of your batch command with a comma. – toti08 Sep 17 '18 at 08:27
  • Check [this question](https://stackoverflow.com/questions/4760215/running-shell-command-from-python-and-capturing-the-output) for more info. – toti08 Sep 17 '18 at 08:28
  • I think you should "native" grep from python... the issue is missing `shell=True` – Jean-François Fabre Sep 17 '18 at 08:34
  • @Jean-FrançoisFabre I have added `shell=True` and i got `CompletedProcess(args=["adb, shell getprop | grep -e 'bt.name'"], returncode=1)` but it still does not store the output – AutoTester213 Sep 17 '18 at 08:36

2 Answers2

7

The issues here:

  • passing arguments like this (string in a list, with spaces) is really not recommended
  • passing arguments like this need shell=True for it to have a slight chance to work, and shell=True is known for security issues (and other issues as well, like non-portability)
  • grep is not standard on windows, and the pattern is a regex which means you'd probably have to escape . ("bt\.name").
  • when not found grep returns 1 and would make check_output fail.
  • when found grep returns match(es), and a newline, that you'd have to strip

I'd rewrite this:

PlatformName = subprocess.check_output(["adb shell getprop | grep -e 'bt.name'"])

as:

output = subprocess.check_output(["adb","shell","getprop"])
platform_name = next((line for line in output.decode().splitlines() if "bt.name" in line),"")

The second line is a "native" version of grep (without regexes). It returns the first occurrence of "bt.line" in the output lines or empty string if not found.

You don't need grep here (the above is not strictly equivalent, as it yields the first occurrence, not all the occurrences but that should be okay on your case). And your clients may not have grep installed on Windows.

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
2

Hey I got the same problem as you. Sub-process can do what you want even with the shell=False. The trick is the communicate() method.

with subprocess.Popen(cmdCode,
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE,
                            cwd = workingDir,
                            bufsize=1,
                            universal_newlines = True) as proc:
    #output is stored in proc.stdout
    #errors are stored in proc.stderr

Now you just need a little function to scan the proc.stdout for the information you need: PlatformName, etc

Sharku
  • 1,052
  • 1
  • 11
  • 24