2

I'm not great on all the technical terms so I'll do my best to explain my problem.

I've written a small script to open android SDK and check for attached devices (using windows 10 and python 2.7.14). The code I've got is as follows:

import os
import datetime
import time

print 'Current Directory:', os.getcwd()
print 'Opening Android SDK...'
os.chdir('C:\\android-sdk\\platform-tools')
print 'Current Directory:', os.getcwd()
t = time.ctime()
print t
print 'Checking for connected devices:'
os.system('adb devices -l')

That all works fine, but I want to get the last 3 lines to save to a text file. I've tried f = open('logfile.txt', 'w') then converting it all to a string using s = str(t, 'Checking for connected devices:', os.system('adb devices -l')) and writing it to the file and closing it, but it's not working. It's not even creating the file, let alone writing anything to it.

I'm probably missing something key but I'm a newbie at this so please be nice!

Any help would be much appreciated.

Many thanks

Edit: whole code with the write stuff included:

import os
import datetime
import time

print 'Current Directory:', os.getcwd()
print 'Opening Android SDK...'
os.chdir('C:\\android-sdk\\platform-tools')
print 'Current Directory:', os.getcwd()
t = time.ctime()
f = open('logfile.txt', 'w')
s = str(t, 'Checking for connected devices:', os.system('adb devices -l'))
f.write(s)
f.close()
Modus Tollens
  • 5,083
  • 3
  • 38
  • 46
elarinya17
  • 57
  • 3
  • 8
  • 2
    Use [`subprocess.check_output`](https://docs.python.org/3/library/subprocess.html#subprocess.check_output) – L3viathan Jan 25 '18 at 11:21
  • if the file doesn't exist try opening in `append` mode. use `with open("filename.txt", "a") as f:` – ShivaGaire Jan 25 '18 at 11:21
  • 1
    @GeekSambhu opening a file in write mode creates it if it doesn't exist yet (and truncate it if it does), so opening in append mode wont change much here (wrt/ file creation I mean). – bruno desthuilliers Jan 25 '18 at 11:23
  • Why don't you paste here your whole code with the file write so we can fix it and tell you where the problem is? – F. Leone Jan 25 '18 at 11:26
  • 1
    `os.system` writes directly to its shell's `stdout`, it's not designed to allow you to capture that output (although you _could_ capture it via shell redirection). Generally, you should use one of the `subprocess` functions instead of the very primitive `os.system`. – PM 2Ring Jan 25 '18 at 11:27
  • @F.Leone edited to include what I've tried – elarinya17 Jan 25 '18 at 11:29
  • 2
    If you are writing new code, you should definitely be targetting Python 3 now. – tripleee Jan 25 '18 at 11:30
  • @PM2Ring thanks, I'll look in to that – elarinya17 Jan 25 '18 at 11:30
  • 1
    Possible duplicate of [Return value of x = os.system(..)](https://stackoverflow.com/questions/26005583/return-value-of-x-os-system) – tripleee Jan 25 '18 at 11:31
  • See also [Running shell command and capturing the output](https://stackoverflow.com/questions/4760215/running-shell-command-and-capturing-the-output) (e.g. as a Python string). – tripleee Jul 24 '20 at 13:01

4 Answers4

2

os.system executes the command in a subshell and returns the command's exit code. It does not provide any mean to capture the outputs of the command ("outputs" => what the command prints to it's stdout/stderr streams).

To capture the command's outputs you'll have to use some of the subprocess module's feature, the most obvious here being subprocess.check_output

# ...
import subprocess
# ...
# NB : you may want to catch subprocess.CalledProcessError here
out = subprocess.check_output(['adb',  'devices', '-l'])
msg = "{t}\nChecking for connected devices:\n{out}".format(t=t, out=out)
with open('logfile.txt', 'w') as f:
    f.write(msg)
bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118
  • @elarinya17 added a Q&D example (untested obviously since I dont have adb installed here). – bruno desthuilliers Jan 25 '18 at 11:38
  • I'm getting some errors, I think it's because it's not recognising the adb command anymore. – elarinya17 Jan 25 '18 at 11:44
  • Ok I fixed the error (just needed a comma between 'devices' and '-l', but now it's just not running the adb command at all, and not creating a text file either – elarinya17 Jan 25 '18 at 11:46
  • Yes I saw the error too (and fixed it in my answer). wrt/ the "it's just not running...": if you have an error, please post the error message, the full traceback, and the _exact_ code that produced the error (edit your question, dont post this in a comment). Else, add some traces in your code (ie `print "calling command"` before the subprocess call and `print "out : '{}'".format(out)` just after the subprocess call. Basic debugging stuff really. – bruno desthuilliers Jan 25 '18 at 11:50
  • Thank you for your help, fixed it now! – elarinya17 Jan 25 '18 at 11:55
  • @elarinya17 then you may want to edit your post to add the working solution so someone else having a similar problem can find it (don't remove the original code and question, _add_ the solution at the bottom). – bruno desthuilliers Jan 25 '18 at 11:57
  • @brunodesthuilliers OPs answer should be posted as answer and not be edited into the question. – Modus Tollens Jan 25 '18 at 12:07
  • 1
    @ModusTollens you're right indeed, my bad. elarinya17 if you read this... – bruno desthuilliers Jan 25 '18 at 12:13
0

Try the following:

import os 
import subprocess 
import time 

print ('Current Directory: {}'.format(os.getcwd()) ) 
print ('Opening Android SDK...') 
os.chdir('C:\\android-sdk\\platform-tools') 
print ('Current Directory: {}'.format(os.getcwd()) )
t = str(time.ctime()) 
try:
    process_output = subprocess.check_output(["adb", "devices", "-l"])
except: #Add here the type of exception you want to raise and logic
    print("Please check your ADB installation and syntax.")
s = ('{} Checking for connected devices: {}'.format(t,process_output) ) 
with open('logfile.txt', 'w') as f:
    f.write(s) 
tripleee
  • 175,061
  • 34
  • 275
  • 318
F. Leone
  • 594
  • 3
  • 14
  • Tried this, it removed the output of the adb command and still hasn't created a text file :( – elarinya17 Jan 25 '18 at 11:42
  • Try to print s and see whats inside, unfortunately i can't install adb to run it since i don't have root access on my current machine – F. Leone Jan 25 '18 at 11:45
  • When I do that it outputs exactly what I need it to (everything that's been written to it), but i still can't actually find the text file? – elarinya17 Jan 25 '18 at 11:47
  • umh weird, try to create a new folder, put the script inside and run it from there, does it create the `logfile.txt`? – F. Leone Jan 25 '18 at 11:51
  • Right it was me being an idiot... I was looking for it in the folder where the original .py file was, it's in the platform-tools folder, which is pretty obvious now I stop and think. -_- Thank you for your help!! – elarinya17 Jan 25 '18 at 11:52
  • @F.Leone I would personnaly do the `subprocess` call (and string formatting) outside the `with` block (and do the `subprocess` call outside the string formatting) - this makes debugging and exception handling easier, and doesn't open (and truncate...) the file uselessly if anything goes wrong. – bruno desthuilliers Jan 25 '18 at 11:59
  • @brunodesthuilliers Good call, i'll edit the post, thanks – F. Leone Jan 25 '18 at 12:03
0

Thanks everyone for your help. The answer was:

import os
import time
import subprocess

print 'Current Directory:', os.getcwd()
print 'Opening Android SDK...'
os.chdir('C:\\android-sdk\\platform-tools')
print 'Current Directory:', os.getcwd()
print 'Checking for connected devices:'
t = time.ctime()
# save log of time and connected devices
with open('logfile.txt', 'w') as f:
    s = ('{}\n{}'.format(t, subprocess.check_output(["adb", "devices", "-l"])))
    f.write(s)
print(s)
elarinya17
  • 57
  • 3
  • 8
  • This is now identical to the accepted answer. Perhaps just delete this as it doesn't contribute anything. – tripleee Jan 25 '18 at 12:48
  • I'ma just leave it here because I got told off for not posting it before, and then told off for posting it in the wrong place. – elarinya17 Jan 25 '18 at 13:20
0

With Python 3.5+ you can (and probably should) use subprocess.run() which conveniently replaces the legacy subprocess.check_output() with a more versatile API.

import subprocess

with open('logfile.txt', 'w') as f:
    subprocess.run(['adb', 'devices', '-l'], stdout=f,
        universal_newlines=True)  # this obscurely makes everything Unicode

Directly connecting the stdout of the subprocess to an open file handle is possible via the old check_output() API too, mind you.

tripleee
  • 175,061
  • 34
  • 275
  • 318