5

Is it possible to read information being sent over LogCat in python?

I have a program that is written in java. Every draw frame it sends tag:"Fps: " message: number

I would like this message to fire an event that I can catch in my python script so I can draw a fps-meter.

user1501445
  • 95
  • 1
  • 1
  • 5

2 Answers2

11

Take a look at subprocess. The following code was adapted from Stefaan Lippens

import Queue
import subprocess
import threading


class AsynchronousFileReader(threading.Thread):
    '''
    Helper class to implement asynchronous reading of a file
    in a separate thread. Pushes read lines on a queue to
    be consumed in another thread.
    '''

    def __init__(self, fd, queue):
        assert isinstance(queue, Queue.Queue)
        assert callable(fd.readline)
        threading.Thread.__init__(self)
        self._fd = fd
        self._queue = queue

    def run(self):
        '''The body of the tread: read lines and put them on the queue.'''
        for line in iter(self._fd.readline, ''):
            self._queue.put(line)

    def eof(self):
        '''Check whether there is no more content to expect.'''
        return not self.is_alive() and self._queue.empty()


# You'll need to add any command line arguments here.
process = subprocess.Popen(["logcat"], stdout=subprocess.PIPE)

# Launch the asynchronous readers of the process' stdout.
stdout_queue = Queue.Queue()
stdout_reader = AsynchronousFileReader(process.stdout, stdout_queue)
stdout_reader.start()

# Check the queues if we received some output (until there is nothing more to get).
while not stdout_reader.eof():
    while not stdout_queue.empty():
        line = stdout_queue.get()
        if is_fps_line(line):
            update_fps(line)

Of course, you'll need to write the is_fps_line and update_fps functions yourself.

jfocht
  • 1,704
  • 1
  • 12
  • 16
  • Cool, Thanks man! :D Was exaaactly what I was looking for :)))) – user1501445 Jul 17 '12 at 14:45
  • doesnt work though xD gives this error: Traceback (most recent call last): File "C:\Users\user\Desktop\Eclipse Workspace\ThirdWorkspace\test.pydev\src\FpsMeter.py", line 116, in process = subprocess.Popen(["logcat"], stdout=subprocess.PIPE) File "C:\Python27\lib\subprocess.py", line 679, in __init__ errread, errwrite) File "C:\Python27\lib\subprocess.py", line 896, in _execute_child startupinfo) WindowsError: [Error 2] The system cannot find the file specified – user1501445 Jul 17 '12 at 14:51
  • The line marked contains this code: process = subprocess.Popen(["logcat"], stdout=subprocess.PIPE) – user1501445 Jul 17 '12 at 14:54
  • This code assumes that logcat is on your path. If it isn't on your runtime path, then you need to provide the full path for logcat (e.g. "C:\Program Files\...\logcat") in replace of the "logcat" string. – jfocht Jul 17 '12 at 17:59
  • logcat doesnt exist in the android dir. You can launch android via "adb logcat" in console though... Event providing the full path C:\Program Files (x86)\Android\android-sdk\platform-tools\logcat it doesnt work. – user1501445 Jul 18 '12 at 06:41
  • If adb is on your path then then you can use `process = subprocess.Popen(["adb", "logcat"], stdout=subprocess.PIPE)` – jfocht Jul 18 '12 at 13:55
  • This one works.. but can someone tell me how can I stop collecting the logs when a particular condition is met? – Harish Talanki Oct 13 '15 at 05:45
  • Did you try with SIGTERM,? or at least subprocess.kill() ?? Reference https://stackoverflow.com/questions/4789837/how-to-terminate-a-python-subprocess-launched-with-shell-true and https://docs.python.org/3/library/subprocess.html – JeanCarlos Chavarria Aug 22 '19 at 05:13
6

I would redirect adb logcat to your python script. This would look like:

$ adb logcat | python yourscript.py

Now you can read from logcat on sys.stdin and parse it however you like.

mfsiega
  • 2,852
  • 19
  • 22