2018-10-06 16:49:06 +00:00
|
|
|
#!/usr/bin/env python
|
2019-10-23 20:10:03 +00:00
|
|
|
import PySimpleGUI as sg
|
2018-10-06 16:49:06 +00:00
|
|
|
import os
|
|
|
|
import signal
|
|
|
|
import psutil
|
|
|
|
import operator
|
|
|
|
|
2019-06-12 15:23:47 +00:00
|
|
|
CONFIRM_KILLS = False
|
2018-10-06 16:49:06 +00:00
|
|
|
|
2020-09-18 17:04:01 +00:00
|
|
|
|
|
|
|
|
2018-10-06 16:49:06 +00:00
|
|
|
"""
|
2018-10-07 02:42:47 +00:00
|
|
|
Utility to show running processes, CPU usage and provides way to kill processes.
|
|
|
|
Based on psutil package that is easily installed using pip
|
2021-03-16 12:06:24 +00:00
|
|
|
|
|
|
|
Copyright 2021 PySimpleGUI
|
2018-10-06 16:49:06 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
def kill_proc_tree(pid, sig=signal.SIGTERM, include_parent=True,
|
|
|
|
timeout=None, on_terminate=None):
|
|
|
|
"""Kill a process tree (including grandchildren) with signal
|
|
|
|
"sig" and return a (gone, still_alive) tuple.
|
|
|
|
"on_terminate", if specified, is a callabck function which is
|
|
|
|
called as soon as a child terminates.
|
|
|
|
"""
|
|
|
|
if pid == os.getpid():
|
|
|
|
raise RuntimeError("I refuse to kill myself")
|
|
|
|
parent = psutil.Process(pid)
|
|
|
|
children = parent.children(recursive=True)
|
|
|
|
if include_parent:
|
|
|
|
children.append(parent)
|
|
|
|
for p in children:
|
|
|
|
p.send_signal(sig)
|
|
|
|
gone, alive = psutil.wait_procs(children, timeout=timeout,
|
|
|
|
callback=on_terminate)
|
|
|
|
return (gone, alive)
|
|
|
|
|
|
|
|
|
2019-06-12 15:23:47 +00:00
|
|
|
def show_list_by_name(window):
|
|
|
|
psutil.cpu_percent(interval=.1)
|
|
|
|
procs = psutil.process_iter()
|
2021-03-16 12:06:24 +00:00
|
|
|
all_procs = []
|
|
|
|
for proc in procs:
|
|
|
|
pinfo = [proc.cpu_percent(), proc.name(), proc.pid]
|
|
|
|
try:
|
|
|
|
cmd = proc.cmdline()
|
|
|
|
pinfo.append(' '.join(cmd))
|
|
|
|
except:
|
|
|
|
pinfo.append('')
|
|
|
|
all_procs.append(pinfo)
|
|
|
|
# all_procs = [[proc.cpu_percent(), proc.name(), proc.pid, proc.cmdline()] for proc in procs]
|
2019-06-12 15:23:47 +00:00
|
|
|
sorted_by_cpu_procs = sorted(all_procs, key=operator.itemgetter(1), reverse=False)
|
|
|
|
display_list = []
|
|
|
|
for process in sorted_by_cpu_procs:
|
2021-03-16 12:06:24 +00:00
|
|
|
display_list.append('{:5d} {:5.2f} {} {}\n'.format(process[2], process[0] / 10, process[1], process[3]))
|
|
|
|
window['-PROCESSES-'].update(display_list)
|
2019-06-12 15:23:47 +00:00
|
|
|
return display_list
|
|
|
|
|
2018-10-06 16:49:06 +00:00
|
|
|
def main():
|
|
|
|
|
|
|
|
# ---------------- Create Form ----------------
|
2020-09-18 17:04:01 +00:00
|
|
|
sg.theme('Dark Grey 9')
|
2018-10-07 03:52:11 +00:00
|
|
|
|
2018-10-06 16:49:06 +00:00
|
|
|
layout = [[sg.Text('Process Killer - Choose one or more processes',
|
2020-09-18 17:04:01 +00:00
|
|
|
size=(45,1), font=('Helvetica', 15), text_color='yellow')],
|
2021-10-13 10:00:03 +00:00
|
|
|
[sg.Listbox(values=[' '], size=(130, 30), select_mode=sg.SELECT_MODE_EXTENDED, horizontal_scroll=True, font=('Courier', 12), key='-PROCESSES-')],
|
2021-07-21 14:18:06 +00:00
|
|
|
[sg.Col([
|
2018-10-06 16:49:06 +00:00
|
|
|
[sg.Text('Click refresh once or twice.. once for list, second to get CPU usage')],
|
2021-03-16 12:06:24 +00:00
|
|
|
[sg.Text('Filter by typing name', font='ANY 14'), sg.Input(size=(15,1), font='any 14', key='-FILTER-')],
|
2018-10-29 00:01:03 +00:00
|
|
|
[sg.Button('Sort by Name', ),
|
|
|
|
sg.Button('Sort by % CPU', button_color=('white', 'DarkOrange2')),
|
|
|
|
sg.Button('Kill', button_color=('white','red'), bind_return_key=True),
|
2021-07-21 14:18:06 +00:00
|
|
|
sg.Exit(button_color=('white', 'sea green')), sg.Sizegrip()]], expand_x=True) ]]
|
2018-10-06 16:49:06 +00:00
|
|
|
|
2019-10-23 20:10:03 +00:00
|
|
|
window = sg.Window('Process Killer', layout,
|
2018-10-06 16:49:06 +00:00
|
|
|
keep_on_top=True,
|
|
|
|
auto_size_buttons=False,
|
2018-10-07 18:18:52 +00:00
|
|
|
default_button_element_size=(12,1),
|
2018-10-07 02:42:47 +00:00
|
|
|
return_keyboard_events=True,
|
2021-07-21 14:18:06 +00:00
|
|
|
resizable=True,
|
|
|
|
right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT,
|
2019-10-23 20:10:03 +00:00
|
|
|
finalize=True)
|
2021-07-21 14:18:06 +00:00
|
|
|
window['-PROCESSES-'].expand(True, True)
|
|
|
|
window.set_min_size(window.size)
|
2019-06-12 15:23:47 +00:00
|
|
|
display_list = show_list_by_name(window)
|
2018-10-06 16:49:06 +00:00
|
|
|
# ---------------- main loop ----------------
|
2019-10-23 20:10:03 +00:00
|
|
|
while True:
|
2018-10-06 16:49:06 +00:00
|
|
|
# --------- Read and update window --------
|
2019-10-23 20:10:03 +00:00
|
|
|
event, values = window.read()
|
2020-05-07 10:22:59 +00:00
|
|
|
if event in (sg.WIN_CLOSED, 'Exit'):
|
2018-10-29 00:01:03 +00:00
|
|
|
break
|
|
|
|
|
|
|
|
# skip mouse, control key and shift key events entirely
|
2018-10-15 20:07:23 +00:00
|
|
|
if 'Mouse' in event or 'Control' in event or 'Shift' in event:
|
2018-10-07 18:18:52 +00:00
|
|
|
continue
|
2018-10-06 16:49:06 +00:00
|
|
|
|
2018-10-29 00:01:03 +00:00
|
|
|
# --------- Do Button Operations --------
|
2018-10-15 20:07:23 +00:00
|
|
|
if event == 'Sort by Name':
|
2019-06-12 15:23:47 +00:00
|
|
|
display_list = show_list_by_name(window)
|
|
|
|
# psutil.cpu_percent(interval=.1)
|
|
|
|
# procs = psutil.process_iter()
|
|
|
|
# all_procs = [[proc.cpu_percent(), proc.name(), proc.pid] for proc in procs]
|
|
|
|
# sorted_by_cpu_procs = sorted(all_procs, key=operator.itemgetter(1), reverse=False)
|
|
|
|
# display_list = []
|
|
|
|
# for process in sorted_by_cpu_procs:
|
|
|
|
# display_list.append('{:5d} {:5.2f} {}\n'.format(process[2], process[0]/10, process[1]))
|
2021-03-16 12:06:24 +00:00
|
|
|
# window['-PROCESSES-'].update(display_list)
|
2021-07-21 14:18:06 +00:00
|
|
|
new_output = []
|
|
|
|
for line in display_list:
|
|
|
|
if values['-FILTER-'] in line.lower():
|
|
|
|
new_output.append(line)
|
|
|
|
window['-PROCESSES-'].update(new_output)
|
2018-10-15 20:07:23 +00:00
|
|
|
elif event == 'Kill':
|
2021-03-16 12:06:24 +00:00
|
|
|
processes_to_kill = values['-PROCESSES-']
|
2018-10-06 16:49:06 +00:00
|
|
|
for proc in processes_to_kill:
|
|
|
|
pid = int(proc[0:5])
|
2019-10-23 20:10:03 +00:00
|
|
|
# if sg.popup_yes_no('About to kill {} {}'.format(pid, proc[12:]), keep_on_top=True) == 'Yes':
|
2019-06-12 15:23:47 +00:00
|
|
|
try:
|
|
|
|
kill_proc_tree(pid=pid)
|
|
|
|
except:
|
2021-03-16 12:06:24 +00:00
|
|
|
sg.popup_non_blocking('Error killing process', auto_close_duration=2, auto_close=True, keep_on_top=True)
|
2018-10-15 20:07:23 +00:00
|
|
|
elif event == 'Sort by % CPU':
|
2019-06-12 15:23:47 +00:00
|
|
|
psutil.cpu_percent(interval=.1)
|
2018-10-07 18:18:52 +00:00
|
|
|
procs = psutil.process_iter()
|
|
|
|
all_procs = [[proc.cpu_percent(), proc.name(), proc.pid] for proc in procs]
|
2021-10-13 10:00:03 +00:00
|
|
|
# procs = psutil.process_iter()
|
|
|
|
# for proc in procs:
|
|
|
|
# sg.Print(sg.obj_to_string_single_obj(proc))
|
2018-10-07 18:18:52 +00:00
|
|
|
sorted_by_cpu_procs = sorted(all_procs, key=operator.itemgetter(0), reverse=True)
|
|
|
|
display_list = []
|
|
|
|
for process in sorted_by_cpu_procs:
|
|
|
|
display_list.append('{:5d} {:5.2f} {}\n'.format(process[2], process[0]/10, process[1]))
|
2021-03-16 12:06:24 +00:00
|
|
|
window['-PROCESSES-'].update(display_list)
|
2021-07-21 14:18:06 +00:00
|
|
|
elif event == 'Edit Me':
|
|
|
|
sg.execute_editor(__file__)
|
2018-10-29 00:01:03 +00:00
|
|
|
else: # was a typed character
|
2018-10-07 18:18:52 +00:00
|
|
|
if display_list is not None:
|
|
|
|
new_output = []
|
|
|
|
for line in display_list:
|
2021-03-16 12:06:24 +00:00
|
|
|
if values['-FILTER-'] in line.lower():
|
2018-10-07 18:18:52 +00:00
|
|
|
new_output.append(line)
|
2021-03-16 12:06:24 +00:00
|
|
|
window['-PROCESSES-'].update(new_output)
|
2020-05-07 10:22:59 +00:00
|
|
|
window.close()
|
2018-10-07 02:42:47 +00:00
|
|
|
|
|
|
|
|
2018-10-06 16:49:06 +00:00
|
|
|
if __name__ == "__main__":
|
2021-03-16 12:06:24 +00:00
|
|
|
main()
|