Python: Mudando o nome de um processo
Índice
Ao executar um aplicativo escrito em Python, Bash, Perl, ou qualquer outra linguagem interpretada no Unix, o sistema irá reconhecer ler a primeira linha do arquivo e assim identificar o seu interpretador, como sendo o comando seguido a sequência de caracteres “#!”, como nos exemplos abaixo:
#!/usr/bin/python
...
para um programa em Python, ou
#!/bin/bash
...
para um scritp em Bash. Em seguida o sistema irá chamar o interpretador, passando o arquivo do programa, como parâmetro de entrada. Com isto o seu programa será identificado por um comando ps, top ou killall, como:
python /path/programa_python
Observe a filtragem dos resultados dos comando ps abaixo, para os aplicativos Python rodando no sistema:
ps x | grep python 2162 ? S 0:17 /usr/bin/python /usr/bin/guidance-power-manager -session 10cdcdd36c000124664523400000031510014_1247632905_833712 2171 ? Ss 0:00 python /usr/bin/hp-systray 2173 ? S 0:01 python /usr/bin/printer-applet 2178 ? S 0:00 python -O /usr/lib64/wicd/wicd-client.py 2193 ? S 0:00 python /usr/bin/hp-systray 2194 ? S 0:00 python /usr/bin/hp-systray 15428 ? Sl 1:06 /usr/bin/python /usr/lib64/python2.6/site-packages/eric4/eric4.py 15434 ? S 0:00 /usr/bin/python /usr/lib64/python2.6/site-packages/eric4/DebugClients/Python/DebugClient.py 58689 1 127.0.0.1 16119 pts/4 S+ 0:00 python 16680 pts/2 S+ 0:00 grep --color=auto python [prompt]ps -A | grep python 2171 ? 00:00:00 python 2173 ? 00:00:01 python 2193 ? 00:00:00 python 2194 ? 00:00:00 python 15428 ? 00:01:06 python 15434 ? 00:00:00 python 16119 pts/4 00:00:00 python
Em alguns casos é importante saber que o interpretador Python está rodando um aplicativo, mas há ocasiões em que esta informação não é de muita ajuda, como quando se necessita matar um aplicativo com comandos como o killall. Um “killall python” seria desastroso, eliminando o primeiro aplicativo python encontrado.
Depois de alguns minutos pesquisando no google, encontrei algumas soluções, as quais são apresentadas a seguir.
1 – Altera o nome em ‘ps -A’, top, killall.
Referência: (stackoverflow.com/questions)
Fiz algumas pequenas alterações para apresentar a proposta com um módulo.
#!/usr/bin/env python
#
from ctypes import cdll, byref, create_string_buffer
# Set a new proc name to application
def setprocname(newname):
""" setprocname(newname): set a new proc name to application """
libc = cdll.LoadLibrary('libc.so.6')
buff = create_string_buffer(len(newname)+1)
buff.value = newname
libc.prctl(15, byref(buff), 0, 0, 0)
# Get a current python proc name
def getprocname():
""" getprocname(): get a current python proc name """
libc = cdll.LoadLibrary('libc.so.6')
buff = create_string_buffer(128)
libc.prctl(16, byref(buff), 0, 0, 0)
return buff.value
if __name__ == '__main__':
while True:
print 'Application name: "%s"' % getprocname()
print 'Enter with a name for application or "q", to exit:'
a = raw_input()
if a == 'q':
break
elif len(a) > 1:
setprocname(a)
print
exit()
2 – Proposta futura
Referência: Marcelo Fernández (http://bugs.python.org/issue5672)
Esta opção é para a próxima versão do Python, provável 2.7, ou quem sabe, para a série a 3. Ela pode ser aplicado como um patch no trunk do Python 2.7. Essencialmente ela faz uma chamada a função prctl() do kernel Linux, para mudar o nome do processo. Isto é feito por adição de dois métodos, ao módulo os, chamados getprocname() e setprocname().
Abaixo segue um exemplo de uso que peguei no link acima:
>>> import os
[34831 refs]
>>> os.getprocname()
'./python'
[34833 refs]
>>> os.getpid()
5601
[34833 refs]
>>> os.setprocname('hello_process_name')
[34833 refs]
>>> os.getprocname()
'hello_process_name'
[34833 refs]
3 – Alterando o argv[0]
Uma outra tentativa que encontrei na rede, foi a de alterar o conteúdo de sys.argv[0]. Aparentemente a ideia veio do Perl, mas não funcionou comigo. O processo também não é portável para outros sistemas como Windows e Mac.
#!/usr/bin/env python
import sys
print sys.argv[0]
sys.argv[0] = 'python_process_name'
while True:
pass
O coloquei aqui apenas para registrar, se o encontrar novamente, tento ver com mais atenção.
4 – Uma outra solução carregada
Referência: Nick Craig-Wood nick at craig-wood.com
Esta me pareceu muito carregada e também não testei. Ela utiliza o vários métodos do módulo ctypes, além do módulo subprocess e os.
#!/usr/bin/python
"""
Attempt to set the process name with ctypes
"""
import os
from subprocess import Popen, PIPE
from ctypes import pythonapi, c_int, c_char_p, POINTER, addressof, pointer, CDLL, memmove, memset
from ctypes.util import find_library
Py_GetArgcArgv = pythonapi.Py_GetArgcArgv
c_lib = CDLL(find_library("c"))
PR_SET_NAME = 15 # linux specific
argc_t = POINTER(c_char_p)
Py_GetArgcArgv.restype = None
Py_GetArgcArgv.argtypes = [POINTER(c_int), POINTER(argc_t)]
def set_name(name):
argv = c_int(0)
argc = argc_t()
Py_GetArgcArgv(argv, pointer(argc))
name0 = name+"\0"
memset(argc.contents, 0, 256) # could do this better!
memmove(argc.contents, name0, len(name0))
# prctl doesn't seem to be needed on linux?
c_lib.prctl(PR_SET_NAME, name+"\0", 0, 0, 0)
def ps():
print Popen(["ps", "v", str(os.getpid())], stdout=PIPE).communicate()[0]
def main():
print "Before"
ps()
set_name("sausage")
print "After"
ps()
if __name__ == "__main__":
main()
Confesso que não me agradou muito, mas acho que merece um lugar ao sol, funciona!
5 – Módulo procname
Ref: http://code.google.com/p/procname/
Acho, mas não tenho certeza, este módulo é o mesmo que foi adicionado a versão 2.7 do Python. O nome do autor não encontrei na página oficial do projeto
>>> import procname
>>> procname.getprocname()
'python'
>>> procname.setprocname('My super-name 9')
Este não testei, pois não compilou em meu Slackware64, mas segundo o autor, isto deve mudar o nome do aplicativo nos comandos ps e top.
Considerações Finais
Pessoalmente acho que isto poderia entrar no header dos scripts em Python, algo como:
#!/usr/bin/env python
#-*- name: python_script_name -*-
... código python
Mas como não existe nada parecido, ao menos por enquanto, vou ficar com a solução 1, aguardando a 2. Ao menos a 1 carrega menos módulos e me parece a mais limpa que a última.
Deixe uma resposta