I try launch adb commands in python without custom modules.
try:
process = subprocess.Popen('cmd.exe', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=None, shell=True)
process.stdin.write("adb shell uninstall com.q.q".encode("utf8"))
process.stdin.write("adb shell install C:\\...\\qwerty.apk".encode("utf8"))
but this not working. Code finish without results
cannot test with your exact commands but that works fine:
import subprocess
process = subprocess.Popen('cmd.exe', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=None, shell=True)
o,e = process.communicate(b"dir\n")
print(o)
(I get the contents of my directory)
so for your example, you're missing the line terminators when sending commands. The commands aren't issued to the cmd program, the pipe is broken before that.
That would work better:
import subprocess
process = subprocess.Popen('cmd.exe', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=None)
process.stdin.write(b"adb shell uninstall com.q.q\n")
process.stdin.write(b"adb shell install C:\\...\\qwerty.apk\n")
o,e = process.communicate()
but this is a very strange way to run commands. Just use check_call, with args split properly:
subprocess.check_call(["adb","shell","uninstall","com.q.q"])
subprocess.check_call(["adb","shell","install",r"C:\...\qwerty.apk"])
Related
I tend to read files name in a Android device beacuse I want to check the resource in this device is correct. Normally the order of manual testing is
adb -s 192.168.1.100:5555 root
adb -s 192.168.1.100:5555 shell
and when enter shell model, into the dir and ls
cd xxx\xxx\xxx
ls
Now I tend to write a python script to help me check it, so I try:
os.system('adb -s 192.168.1.100:5555 root')
obj = subprocess.Popen(["adb -s 192.168.1.100:5555 shell"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
and then I dont't know how to read file name and put file name into a list. Without shell model I try:
file_list = os.listdir("xxx\xxx\xxx")
l = []
for file_name in file_list:
l.append(file_name)
It works, but how can I do this in shell model? I mean switch path to adb shell path, then I can use this code to put file name into a list. Any idea? Thanks!
If you want to print all the files in a particular directory in a shell, you can simply try this:
for i in *; do echo $i;done
Here is what you can put in your python file.
import subprocess
p = subprocess.Popen('for i in *; do echo $i;done', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in p.stdout.readlines():
print line,
This will get your task done.
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.
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)
I am [new to] using Python 2.7 on Windows 7 and I am trying to incorporate adb shell commands to access/change the directories on my Android device. What I need to do is get the size of a directory in Internal Storage, save that output as a variable, and then delete the directory. From my research I believe I should be using subprocess.Popen()to create the shell and then .communicate() to send the required commands. However I am currently only able to execute one of the commands: delete the directory. Below is the code that I used:
import os, subprocess
from subprocess import PIPE, Popen
adb_shell = subprocess.Popen('adb shell', stdin = subprocess.PIPE)
adb_shell.communicate('cd /sdcard\nrm -r "Directory to Delete"\nexit\n')
However, if I add another command by doing:
adb_shell.communicate('cd /sdcard\ndu -sh "Directory A"\nrm -r "Directory A"\nexit\n')
It does not work because I need to incorporate stdout = subprocess.PIPE to store the output of the du -sh "Directory A"command, but how do I go about doing that? If I add it like: adb_shell = subprocess.Popen('adb shell', stdin = subprocess.PIPE, stdout = subprocess.PIPE), it does not work. Any suggestions? ty!
Edit: The closest I've come to a solution (actually getting an output in the interpreter and removing the file afterwards) is with:
adb_shell = subprocess.Popen('adb shell', stdin = subprocess.PIPE, stdout = subprocess.PIPE)
adb_shell.communicate('cd /sdcard\ndu -sh "qpython"\nexit\n')
output = adb_shell.stdout
print output
adb_shell = subprocess.Popen('adb shell', stdin = subprocess.PIPE)
adb_shell.communicate('cd /sdcard\nrm -r "qpython"\nexit\n')
Which has an output of: '', mode 'rb' at 0x02B4D910>'
It's not pretty but it works:
lines = []
get_restore_size = subprocess.Popen('adb shell du -sh /sdcard/qpython', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in get_restore_size.stdout.readlines():
lines.append(line)
restore_size = (lines[0].strip('\t/sdcard/qpython\r\r\n'))
print restore_size
del_restore = subprocess.Popen('adb shell', stdin = subprocess.PIPE)
del_restore.communicate('cd /sdcard\nrm -r "qpython"\nexit\n')
Open to suggestions to improve!
There is no reason for running both commands in the same shell session:
print subprocess.check_output(["adb", "shell", "du -sh /sdcard/qpython"])
subprocess.check_output(["adb", "shell", "rm -r /sdcard/qpython"])
I am trying to execute adb shell commands in python using subprocess.Popen
Example: Need to execute 'command' in adb shell. While executing manually, I open the command window and execute as below and it works.
>adb shell
#<command>
In Python I am using as below but the process is stuck and doesn't give output
subprocess.Popen('adb shell <command>)
Tried executing manually in command window, same result as python code,stuck and doesn't give output
>adb shell <command>
I am trying to execute a binary file in background(using binary file name followed by &) in the command.
Found a way to do it using communicate() method in subprocess module
procId = subprocess.Popen('adb shell', stdin = subprocess.PIPE)
procId.communicate('command1\ncommand2\nexit\n')
use pexpect (https://pexpect.readthedocs.io/en/stable/)
adb="/Users/lishaokai/Library/Android/sdk/platform-tools/adb"
import pexpect
import sys, os
child = pexpect.spawn(adb + " shell")
child.logfile_send = sys.stdout
while True:
index = child.expect(["$","#",pexpect.TIMEOUT])
print index
child.sendline("ls /storage/emulated/0/")
index = child.expect(["huoshan","google",pexpect.TIMEOUT])
print index, child.before, child.after
break
Ankur Kabra, try the code below:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import subprocess
command = 'adb devices'
p = subprocess.Popen(command, shell=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
print 'standard output: %s \n error output: %s \n',(stdout,stderr)
and you will see the error output.
Usually it will tell you:
/bin/sh: adb: command not found
which means, shell can not excute adb command.
so, adding adb to your PATH or writing the full path of adb will solve the problem.
May help.
I am trying to use python to help do some automation around an incremental build function in the Android build system. Generally, from a given directory, I would execute the following command to build whatever is in that directory and subdirectories:
mm -j8
This is analogous to a "make" command, only it is incremental build and is defined as a function in a bash file called envsetup.sh. What is does it not important, just know that it's a function defined in a bash script somewhere in the file system. To execute this, I can also do:
bash -c ". /path/to/envsetup.sh; mm -j8"
This method of calling it will be important in calling the function from python. I have followed the solution here which shows how to call a function within a bash script from python. I have used this method in a simple script that, in theory, should just spit out the STDOUT and STDERR from executing the command:
import subprocess
command = ['bash', '-c', '. /path/to/envsetup.sh; mm -j8']
(stdout, stderr) = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).communicate()
print 'stdout: ' + stdout
print 'stderr: ' + stderr
The call to Popen, however, never returns. What am I doing wrong that would allow bash to execute the command properly, but Python hangs when executing the command?
tl; dr:
Your issue is the use of shell=True. Set it to shell=False and it'll work.
With this option set, python will just run the first element of the command array, i.e. bash as a shell script. So currently, python is launching a shell of its own, in order to run your command (bash). It'll run bash with no arguments, and bash will then wait for input, blocking your python script.
The shell=True setting is for use cases where you are passing a shell script in as a single string. When you're explicitly specifying a shell and its parameters as the process to invoke, as you are doing above, you should set shell=False.
>>> import subprocess
>>> subprocess.Popen(['bash', 'whatever'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).communicate()
Here's what the proces tree looks like when I run the above:
\_ python
\_ /bin/sh -c bash whatever
\_ bash
The whatever is actually passed in, but it's a parameter to the sh, not a parameter to the inner bash, so the command being run is effectively ['/bin/sh', '-c', 'bash', 'whatever'], which is quite different from ['/bin/sh', '-c', 'bash whatever']