O Psutil (Processos e Utilitários do Sistema) é uma biblioteca multi-plataforma para recuperação de informações sobre a execução de processos e utilização do sistema (CPU, memória, discos, rede) em Python. É útil principalmente para a monitorização do sistema, criação de perfis e limitando recursos e gestão de processos em execução do processo.
O mesmo implementa muitas funcionalidades oferecidas pelas ferramentas de linha de comando, tais como: ps, top, lsof, netstat, ifconfig, who, df, kill, free, nice, ionice, iostat, iotop, uptime, pidof, tty, taskset, pmap. Atualmente ele suporta Linux, Windows, OSX, Sun Solaris, FreeBSD, OpenBSD e NetBSD, ambas as arquiteturas de 32 bits e de 64 bits, com versões de Python de 2,6 para 3,5 (usuários do Python 2.4 e 2.5 podem usar 2.1.3 versão).
Resumindo é um Canivete Suíço para auxiliar nos testes automatizados. Como assim? Você pode monitorar o consumo de memoria/processamento do seu aplicativo em um determinado teste, ou verifica o antes e o depois de um determinado teste, tendo o total de consumo de memoria no sistema operacional, você pode criar um testes de instalação do seu produto e verificar se o aplicativo após a instalação esta em memoria, assim como desinstalação do seu produto verificando se foram removidos da memoria do sistema operacional.
Em sistema embarcado já fiz inúmeros testes tendo que pegar a memoria de um determinado teste, por um período de tempo, por exemplo em um teste o Middleware estava travando em uma funcionalidade quando você voltava do Standby. Com o Psutil podemos monitorar esse teste de forma melhor. O Middleware era em linux eu usava o top e o free, em sistemas desktop o Psutil é maravilhoso, podemos verificar monitorar o uso de memoria, processamento, rede e disco.
Vamos aos exemplos práticos, abaixo funções para pegar o pid de um processo passando o nome, matar uma lista de processos via Psutil e via console e também de forma remota, é super prático e rápido.
import subprocess
import psutil
class TaskKill:
def __init__(self):
pass
# funcao que me passa o nome do app e me retorna o pid.
def list_pid(self, app):
pid = ''
if app:
for proc in psutil.process_iter():
try:
pinfo = proc.as_dict(attrs=['pid', 'name'])
if pinfo['name'] == app:
pid = pinfo['pid']
except psutil.NoSuchProcess:
print "o processo nao existe mais."
return pid
else:
print(pinfo)
else:
print "Voce precisa enviar o nome do processo!"
return pid
# funcao que me passa uma lista de processo por nome e me retorna uma lista de processos.
def lista_processos(self, app):
proc_kill = []
for proc in psutil.process_iter():
try:
pinfo = proc.as_dict(attrs=['pid', 'name'])
if pinfo['name'] == app:
proc_kill.append(proc)
except psutil.NoSuchProcess:
print "O processo nao existe mais."
pass
else:
print(pinfo)
return proc_kill
# Funcao que forca matar o processo via force no console.
def kill_force(self, pid):
if pid:
p = psutil.Process(pid)
app = p.name()
for proc in psutil.process_iter():
try:
pinfo = proc.as_dict(attrs=['pid', 'name'])
if pinfo['name'] == app:
print "notepad found!"
subprocess.check_output('taskkill /PID ' + str(pid) + ' /F', shell=True)
return True
except Exception, e:
print "Erro Desconhecido: ", e
pass
else:
print "Pid nao enviado!"
return False
def on_terminate(self, proc):
print("process {} terminated with exit code {}".format(proc, proc.returncode))
# funcao de envia uma lista de processos e mata o processo via psutil.
def psutil_kill(self, procs_kill):
status = False
procs = procs_kill # a list of Process instances
for p in procs:
try:
p.terminate()
print "Terminate processo!"
status = True
except psutil.NoSuchProcess:
print "O processo nao existe mais."
pass
gone, alive = psutil.wait_procs(procs, timeout=10, callback=on_terminate)
for p in alive:
print ("couldn't terminate process %s" % p)
try:
p.kill()
print "Kill processo!"
status = True
except psutil.NoSuchProcess:
print "O processo nao existe mais."
return status
# funcao que matar um processo de forma remota na rede, usando o pskill.
def kill_force_remote(self, computer, pid, user, password):
print "notepad found!"
try:
subprocess.check_output(
'C:\SysinternalsSuite\pskill.exe -t \\' + '\\' + str(computer) + ' -u ' + str(user) + ' -p ' + \
str(password) + ' ' + str(pid), shell=True)
return True
except Exception, e:
print "Erro generico: ", e
return False
if __name__ == '__main__':
obj = TaskKill()
pid_num = obj.list_pid('notepad++.exe')
test = obj.kill_force(pid_num)
print "Kill App: " + str(test)
Resultado:
C:\Python27\python.exe C:/Users/reiload/Dropbox/python_functions/kill_app.py
{'pid': 0, 'name': 'System Idle Process'}
{'pid': 4, 'name': 'System'}
{'pid': 7120, 'name': 'chrome.exe'}
{'pid': 7444, 'name': 'chrome.exe'}
{'pid': 7548, 'name': 'WUDFHost.exe'}
{'pid': 7964, 'name': 'zatray.exe'}
{'pid': 8064, 'name': 'chrome.exe'}
{'pid': 8088, 'name': 'taskhostex.exe'}
{'pid': 8128, 'name': 'GWX.exe'}
{'pid': 9028, 'name': 'python.exe'}
{'pid': 9124, 'name': 'dasHost.exe'}
{'pid': 9272, 'name': 'chrome.exe'}
{'pid': 9368, 'name': 'chrome.exe'}
{'pid': 9396, 'name': 'chrome.exe'}
{'pid': 9556, 'name': 'cmd.exe'}
{'pid': 9820, 'name': 'chrome.exe'}
{'pid': 10084, 'name': 'jucheck.exe'}
{'pid': 10164, 'name': 'cmd.exe'}
{'pid': 10324, 'name': 'audiodg.exe'}
{'pid': 10836, 'name': 'chrome.exe'}
{'pid': 10848, 'name': 'conhost.exe'}
{'pid': 11832, 'name': 'python.exe'}
{'pid': 12316, 'name': 'fsnotifier.exe'}
{'pid': 12320, 'name': 'pycharm.exe'}
{'pid': 12620, 'name': 'conhost.exe'}
{'pid': 12812, 'name': 'python.exe'}
{'pid': 12864, 'name': 'taskeng.exe'}
{'pid': 12932, 'name': 'chrome.exe'}
{'pid': 13080, 'name': 'chrome.exe'}
{'pid': 13188, 'name': 'conhost.exe'}
{'pid': 13544, 'name': 'conhost.exe'}
{'pid': 14564, 'name': 'chrome.exe'}
{'pid': 15032, 'name': 'notepad++.exe'}
notepad found!
Kill App: True
Process finished with exit code 0
Quem já não precisou matar um processo no braço? Aqui temos um exemplo de forma automatizada e super prático em Python. Na função kill_force_remote, se você não sabe qual é o PID, passa o nome do processo que vai funcionar mesmo assim. O que pode ocorrer de o script não funcionar é porque você não tem permissão necessária para o mesmo, podemos adicionar o except psutil.AccessDenied, que vai informar que houve acesso negado. Podemos ir um pouco além com o DDT (data driven test), para fazer ele ler vários processos através de um arquivo de json.
Se você tem um servidor e todo dia tem que matar uma lista de processos na mão, aqui você tem a solução de seus problemas, fazendo isso de forma automatizada, bom espero que gostem e até o próximo Post.
Referências:
[1] http://pythonhosted.org/psutil/
[2] https://pypi.python.org/pypi/psutil
[3] https://technet.microsoft.com/en-us/sysinternals/pskill.aspx
[4] https://pypi.python.org/pypi/ddt