patternpythonMinor
Windows CLI locks killer in Python
Viewed 0 times
killercliwindowspythonlocks
Problem
Some coworkers and I sometimes want to delete folders, only to get the very informative: "Permission Denied" message. I had discovered Handle.exe and Process Explorer to help with this, but the method was still too manual and cumbersome.
Thus, I decided to write this Python CLI script to release locks on a given file. It runs Handle.exe under the hood and parses the output to prompt the user for confirmation to kill any given process (unless a quiet-like option flag is given).
We all work on Windows 7 using basically the same setup (IT takes care of setting up all the machines). The default Python is ActivateState's Python2.6.9. While some people use cmd.exe, a lot of guys use Bash or Cygwin, so I wanted to support all of these.
I am not sure if using
Also, I'm at a loss as to how to test this. I've added tests for
```
"""Dammit let me delete this file!
Usage:
dammit [-y | -s]
dammit (-h)
Options:
-y Kill without permission.
-s Enable hotkey
-h Show this screen.
"""
from __future__ import print_function
from docopt import docopt
from functools import partial
import logging
import msvcrt
import os
import posixpath
import re
import subprocess
import sys
import time
log = logging.getLogger()
log.setLevel(logging.INFO)
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
PREFIX = 'dammit:'
formatter = logging.Formatter(PREFIX + ' %(message)s')
ch.setFormatter(formatter)
log.addHandler(ch)
CYGPATH = ['C:\\GnuNT\\bin\\cygpath.exe']
HANDLE = ["handle64.exe"]
# handle.exe provides way to close specified handle, which would be preferable,
# but this requires administrator rights :(
KILL = ["TASKKILL", "/f", "/pid"]
ACTIVATE = ["activate
Thus, I decided to write this Python CLI script to release locks on a given file. It runs Handle.exe under the hood and parses the output to prompt the user for confirmation to kill any given process (unless a quiet-like option flag is given).
We all work on Windows 7 using basically the same setup (IT takes care of setting up all the machines). The default Python is ActivateState's Python2.6.9. While some people use cmd.exe, a lot of guys use Bash or Cygwin, so I wanted to support all of these.
I am not sure if using
logging solely for the purpose of adding a prefix to my output messages was a good idea, but it felt very redundant to add it to every print. Making a function that wraps print made the code look weird.Also, I'm at a loss as to how to test this. I've added tests for
abspath function (see repo), but I'm having trouble writing tests for the other functions.```
"""Dammit let me delete this file!
Usage:
dammit [-y | -s]
dammit (-h)
Options:
-y Kill without permission.
-s Enable hotkey
-h Show this screen.
"""
from __future__ import print_function
from docopt import docopt
from functools import partial
import logging
import msvcrt
import os
import posixpath
import re
import subprocess
import sys
import time
log = logging.getLogger()
log.setLevel(logging.INFO)
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
PREFIX = 'dammit:'
formatter = logging.Formatter(PREFIX + ' %(message)s')
ch.setFormatter(formatter)
log.addHandler(ch)
CYGPATH = ['C:\\GnuNT\\bin\\cygpath.exe']
HANDLE = ["handle64.exe"]
# handle.exe provides way to close specified handle, which would be preferable,
# but this requires administrator rights :(
KILL = ["TASKKILL", "/f", "/pid"]
ACTIVATE = ["activate
Solution
String formatting
Generally, if you're using Python 2.6 or higher, you should be using the function
Could become this:
Another example would be turning this:
Into this:
Miscellaneous
On a small note, strings like this:
Can be prefixed with
Anything like this:
Can simply be changed to this:
In the case of the
Other than that, your code looks really nice and clean. Good job!
Generally, if you're using Python 2.6 or higher, you should be using the function
str.format to format strings, rather than %. For example, this line in your code:question = " Kill process %s with PID %s [y/n/s]? " % (process, pid)Could become this:
question = " Kill process {process} with PID {pid} [y/n/s]? ".format(
process=process,
pid=pid
)Another example would be turning this:
log.debug("Killed PID %s" % pid)Into this:
log.debug("Killed PID {pid}".format(pid=pid))Miscellaneous
On a small note, strings like this:
'C:\\GnuNT\\bin\\cygpath.exe'Can be prefixed with
r, like this so that you can do this, and get rid of the double-backslashes:r'C:\GnuNT\bin\cygpath.exe'Anything like this:
return NoneCan simply be changed to this:
returnIn the case of the
kill function, the return at the end can be omitted completely.Other than that, your code looks really nice and clean. Good job!
Code Snippets
question = " Kill process %s with PID %s [y/n/s]? " % (process, pid)question = " Kill process {process} with PID {pid} [y/n/s]? ".format(
process=process,
pid=pid
)log.debug("Killed PID %s" % pid)log.debug("Killed PID {pid}".format(pid=pid))'C:\\GnuNT\\bin\\cygpath.exe'Context
StackExchange Code Review Q#96797, answer score: 3
Revisions (0)
No revisions yet.