Sunday, January 23, 2022

MacOS: Pulling Battery Data from IOReg to CSV File using Python and LaunchAgents

 I wanted to track battery data over time and have not found a reasonable approach using the current apps to store the information in a database. I decided the first step was to figure out how to pull the information and store in a CSV file. Next steps include either pushing to PostgresSQL and to Google Sheets.

First I found the ioreg command which enabled me to pull the data. I could have used a shell script but preferred to use Python 3 since it would give me more options in the future.

I used the command 

                            ioreg -rd1 -c AppleSmartBattery

Which enabled me to pull just the battery information I was interested in. I was able to use python to pull specific items and push to a csv file. I'm not sure I got everything I wanted but it is a start. Once the program worked I created a plist file to run it every 60 minutes via LaunchAgent. The cool part of LaunchAgents is the ability to run after coming out of sleep mode.

I did install pyinstaller to create an "executable" which I placed in the bin directory and it writes to a data directory. Below find the program and plist I used. 


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "">

<plist version="1.0">



















import subprocess
from csv import DictWriter
from datetime import datetime

# datetime object containing current date and time
now =
nowDate = now.strftime("%Y%m%d")
nowTime = now.strftime("%H%M%S")
fileName = "/Users/username/data/batteryinfo.csv"

batteryRawInfo = {}
batteryInfo = {}
excludeList = ['+-o', '{', '}', "\r"]
headersCSV = [

def exist_and_not_empty(filepath):
import pathlib as p
path = p.Path(filepath)
if '~' in filepath:
path = path.expanduser()
if not path.exists() and path.stat().st_size > 0:
return False
return True
except FileNotFoundError:
return False

def writeCSVFile(fileName, headers, batDict):
with open(fileName, 'a', newline='') as f_object:
# Pass the CSV file object to the Dictwriter() function
# Result - a DictWriter object
dictwriter_object = DictWriter(f_object, fieldnames=headers)
# Pass the data in the dictionary as an argument into the writerow() function
# Close the file object

def main():

with subprocess.Popen(['ioreg', '-rd1', '-c', 'AppleSmartBattery'], stdout=subprocess.PIPE, text=True) as proc:
# print(proc.__dict__)
# with as stdoutString:,
# print(stdoutString)
batteryLines = proc.stdout.readlines()

for line in batteryLines:
if [ele for ele in excludeList if (ele in line)]:

# print("Line: [{}]".format(line.strip().replace(' ','').replace('"','')))
if "=" in line:
(k, v) = line.strip().replace(' ', '').replace('"', '').split("=")
batteryRawInfo[k] = v

# print("Dictionary ........................... ")
# print(batteryRawInfo)

for key, value in batteryRawInfo.items():
# print(f'Key: {key}, Value: {value}')
if key in headersCSV:
batteryInfo[key] = value

batteryInfo["Date"] = nowDate
batteryInfo["Time"] = nowTime

# print(batteryInfo)
writeCSVFile(fileName, headersCSV, batteryInfo)

if __name__ == '__main__':

I did have some issues loading the launch agent and finally download an application called LaunchControl. Helped with a permissions issue and fixed my issue.