Measuring memory consumption with python
By: Kerim in python
Ever wanted to show your free memory (or other things) in the system tray ?
Since i had a really bad celeron based desktop with 1 gigabyte ram and eclipse consuming some 500 megabytes alone i so often ran into trouble that i thought i might just as well program some tracking program to know when it is time to close some of the applications that i run in paralel.
Since by now i have a 2 gigabyte core 2 duo tower the program is not really needed (for now) anymore.
But i thought i could share it still.
It's based on windows (and runs only there).
For those that are interested in the binary or sources i will put up some links later this week ok ? Need to clean up things first.
Anyway here is the code explained....
You might still know the mailfetcher. Basically it is based on the same skeleton. Some parts are commented because i didn't implement some features yet that i thought might be interesting later (as usual i start new things before finishing the old ones ;-) )
I had plans for a cpu meter as well that would change the color of the background or the font depending on cpu usage.
Its not really nice looking but it works and you might remind me to clean up the code later.
I don't have much time these days.
First the imports
import sys, wx, webbrowser import mem from ctypes import * ID_ICON_TIMER = wx.NewId() OPEN_BROWSER=wx.NewId()
Now come two classes. the taskbaricon itself and the application.
Mainly we follow the scheme of MailSneaker.
class StatusMeterTaskBarIcon(wx.TaskBarIcon): def __init__(self, parent): wx.TaskBarIcon.__init__(self) self.parentApp = parent self.CreateMenu() # Create the menu def CreateMenu(self): self.Bind(wx.EVT_TASKBAR_RIGHT_UP, self.ShowMenu) self.Bind(wx.EVT_MENU, self.parentApp.OpenBrowser, id=OPEN_BROWSER) self.menu=wx.Menu() self.menu.Append(OPEN_BROWSER, "Visit codeboje","This will open a new Browser tab") self.menu.AppendSeparator() self.menu.Append(wx.ID_EXIT, "Close App") def ShowMenu(self,event): self.PopupMenu(self.menu) #This will create and set the icon that is displayed in the taskbar def SetIconImage(self,text,font=None,fgColor=wx.WHITE,bgColor=wx.BLACK_BRUSH): #create a new empty icon and an empty bitmap for the text self.noIcon = wx.EmptyIcon() self.bitmap=wx.EmptyBitmap(48,48) #create a MemoryDC for the pain operations memory = wx.MemoryDC() #Set the font depending on the length of the text (TODO: not yet looking good for # sizes > 1 GB) if len(text)>3: if not font: font=self.createDefaultFont() size = font.GetPointSize()-1 size=size-2 font.SetPointSize(size) memory.SetFont(font) else: if not font: font=self.createDefaultFont() size = font.GetPointSize()-1 font.SetPointSize(size) memory.SetFont(font) #set the foreground color if fgColor: memory.SetTextForeground( fgColor ) #write free mem size into the bitmap self.write(text,self.bitmap,memory,(0,0),fgColor,bgColor) #copy bitmap data into the icon self.noIcon.CopyFromBitmap(self.bitmap) #set the icon self.SetIcon(self.noIcon, "Free mem:"+text+ "megabytes") #if no font is given this font will be used def createDefaultFont(self): font=wx.FFont(21,wx.FONTFAMILY_DEFAULT) return font #writes the size of free memory onto the bitmap after drawing the background def write(self, text, bitmap, memory,pos=(0,0), fgColor=wx.WHITE, bgColor=wx.GREEN_BRUSH): memory.SelectObject( bitmap ) memory.SetBrush(bgColor) try: memory.DrawRectangle(pos[0],pos[1],48,48) memory.DrawText(text, pos[0],pos[1]) finally: memory.SelectObject( wx.NullBitmap) return bitmap
Now the magic goes in SetIconImage and write.
The explanation should be understandable
Now comes the app itself. Basically it's the same as for MailSneaker. I didn't even bother to rename every member.
class StatusMeterFrame(wx.Frame): def __init__(self, parent, id, title): wx.Frame.__init__(self, parent, -1, title, size = (1, 1), style=wx.FRAME_NO_TASKBAR|wx.NO_FULL_REPAINT_ON_RESIZE) self.tbicon = StatusMeterTaskBarIcon(self) self.tbicon.Bind(wx.EVT_MENU, self.exitApp, id=wx.ID_EXIT) self.timer=wx.Timer(self) self.Bind(wx.EVT_TIMER, self.CheckMemory) self.timer.Start(300) # 300 milliseconds self.Show(True) def exitApp(self,event): self.timer.Stop() self.tbicon.RemoveIcon() self.tbicon.Destroy() sys.exit() def OpenBrowser(self,event): webbrowser.open('http://codeboje.de/blog/pages/donate.html') def OpenPrefs(self,event): pass def CheckMemory(self,event): memstatus = mem._MEMORYSTATUS() windll.kernel32.GlobalMemoryStatus(byref(memstatus )) total,free= memstatus.show() ffree=int(float(free)/1048576) #in megabytes self.tbicon.SetIconImage(str(ffree)) #---------------- run the program ----------------------- def main(argv=None): app = wx.App(False) frame = StatusMeterFrame(None, -1, ' ') frame.Show(False) app.MainLoop() if __name__ == '__main__': main()
To get the memory i use this function. As you can see this will only work on windows. If anybody has some working unix call i would be happy to add those
:::python def CheckMemory(self,event): memstatus = mem._MEMORYSTATUS() windll.kernel32.GlobalMemoryStatus(byref(memstatus )) total,free= memstatus.show() ffree=int(float(free)/1048576) #in megabytes self.tbicon.SetIconImage(str(ffree))
PS: Did i mention a flaw (thanks wxPython) ? The program consumes some 20 megabytes itself lol.
EDIT
As you can see in the comments section i forgot something.
The "mem" module. Here it is:
:::python from ctypes import * from ctypes.wintypes import DWORD
SIZE_T = c_ulong
class _MEMORYSTATUS(Structure):
_fields_ = [("dwLength", DWORD),
("dwMemoryLength", DWORD),
("dwTotalPhys", SIZE_T),
("dwAvailPhys", SIZE_T),
("dwTotalPageFile", SIZE_T),
("dwAvailPageFile", SIZE_T),
("dwTotalVirtual", SIZE_T),
("dwAvailVirtualPhys", SIZE_T)]
def show(self):
return (int(getattr(self,"dwTotalPhys")),int(getattr(self,"dwAvailPhys")))
#test routine
memstatus = _MEMORYSTATUS()
windll.kernel32.GlobalMemoryStatus(byref(memstatus ))
total,free= memstatus.show()
print total
print free




on 9 June 2007 at 17:10 mrgomel said …
AFAIK a mem package is not standard. Where did you get it from?
on 10 June 2007 at 09:59 kerim said …
You are correct. mem is a class i wrote to store the data of the windll.kernel32.GlobalMemoryStatus query similar to that snipplet of the ctypes documentation you can find here:
http://docs.python.org/dev/lib/ctypes-bit-fields-in-structures-unions.html
I thought it might be usefull for other things as well.
I have the code on my office pc and will add it to the blog entry tomorrow.