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.