diff --git a/cleanup b/cleanup
index bee88ea79d978d6ea0ba05120bfb5ecc5e4def27..f3294b54ebd22e59e829b980db8ab4072551bf87 100755
--- a/cleanup
+++ b/cleanup
@@ -1,33 +1,57 @@
-#!/bin/bash
-
-# Unfortunately, Mininet and OpenFlow don't always clean up
-# properly after themselves. Until they do (or until cleanup
-# functionality is integrated into the python code), this
-# script may be used to get rid of unwanted garbage. It may
-# also get rid of "false positives", but hopefully nothing
-# irreplaceable!
-
-echo "Removing all links of the pattern foo-ethX"
-
-for f in `ip link show | egrep -o '(\w+-eth\w+)' ` ; do  
-  cmd="ip link del $f"
-  echo $smd
-  $cmd
-done
-
-echo "Removing excess controllers/ofprotocols/ofdatapaths/pings"
-killall -9 controller ofprotocol ofdatapath ping 2> /dev/null
-
-echo "Removing excess kernel datapath processes"
-ps ax | egrep -o 'dp[0-9]+' | sed 's/dp/nl:/' | xargs -l1 echo dpctl deldp 
-
-echo "Removing junk in /tmp"
-rm -f /tmp/vconn* /tmp/vlogs* /tmp/*.out /tmp/*.log
-
-echo "Killing nox"
-killall lt-nox_core
-killall nox_core
-
-echo "Removing old screen sessions"
-screen -ls | egrep -o '[0-9]+\.[hsc][0-9]+' | sed 's/\.[hsc][0-9]*//g' | kill -9
-
+#!/usr/bin/python
+
+"""
+Unfortunately, Mininet and OpenFlow don't always clean up
+properly after themselves. Until they do (or until cleanup
+functionality is integrated into the python code), this
+script may be used to get rid of unwanted garbage. It may
+also get rid of 'false positives', but hopefully nothing
+irreplaceable!
+"""
+
+from subprocess import Popen, PIPE
+import re
+
+def sh( cmd ): 
+   "Print a command and send it to the shell"
+   print cmd
+   return Popen( [ '/bin/sh', '-c', cmd ], 
+      stdout=PIPE ).communicate()[ 0 ]
+
+def cleanUpScreens():
+   "Remove moldy old screen sessions."      
+   r = r'(\d+.[hsc]\d+)'
+   output = sh( 'screen -ls' ).split( '\n' )
+   for line in output:
+      m = re.search( r, line )
+      if m is not None:
+         quietRun( 'screen -S ' + m.group( 1 ) + ' -X kill' )
+ 
+def cleanup():
+   print "*** Removing all links of the pattern foo-ethX"
+   links = sh( "ip link show | egrep -o '(\w+-eth\w+)'" ).split( '\n' )
+   for link in links: 
+      if link: sh( "ip link del " + link )
+
+   print "*** Removing excess controllers/ofprotocols/ofdatapaths/pings/noxes"
+   zombies = 'controller ofprotocol ofdatapath ping nox_core lt-nox_core'
+   # Note: real zombie processes can't actually be killed, since they 
+   # are already (un)dead. Then again,
+   # you can't connect to them either, so they're mostly harmless.
+   sh( 'killall -9 ' + zombies + ' 2> /dev/null' )
+
+   print "*** Removing excess kernel datapaths"
+   dps = sh( "ps ax | egrep -o 'dp[0-9]+' | sed 's/dp/nl:/'" ).split( '\n')
+   for dp in dps: 
+      if dp: sh( 'ip link del ' + link )
+
+   print "*** Removing junk from /tmp"
+   sh( 'rm -f /tmp/vconn* /tmp/vlogs* /tmp/*.out /tmp/*.log' )
+
+   print "*** Removing old screen sessions"
+   cleanUpScreens()
+
+   print "*** Cleanup complete."
+
+if __name__ == "__main__":
+   cleanup()