2010-05-21 18 views
7

Estoy trabajando con un sistema de clúster sobre Linux (www.mosix.org) que me permite ejecutar trabajos y hacer que el sistema los ejecute en diferentes computadoras. Se ejecutan trabajos de este modo:Cómo indicar la identificación del proceso dentro de Python

mosrun ls & 

Esto, naturalmente, el proceso de crear y ejecutarlo en el fondo, devolviendo el identificador de proceso, así:

[1] 29199 

Más tarde se volverá. Estoy escribiendo una infraestructura de Python que ejecutaría trabajos y los controlaría. Para eso quiero ejecutar trabajos utilizando el programa mosrun como se indica anteriormente, y guardar el ID del proceso engendrado (29199 en este caso). Esto, naturalmente, no se puede hacer utilizando os.system o commands.getoutput, ya que la identificación impresa no es lo que el proceso imprime para dar salida ... ¿Alguna pista?

Editar:

Dado que el script en Python, sólo está pensada para funcionar inicialmente el guión, los guiones necesidad de correr más tiempo que el intérprete de Python. Supongo que significa que el proceso de mosrun no puede ser el proceso secundario del script. ¿Alguna sugerencia?

Gracias

+0

Normalmente, los procesos secundarios siguen ejecutándose cuando el proceso principal fallece. –

Respuesta

2

Parece que desea asegurarse de que el proceso secundario es daemonized - PEP 3143, que estoy señalando, documenta y apunta a una implementación de referencia para eso, y apunta a otros también.

Una vez que se endemoniada su proceso (aún en marcha el código Python), ya sea por los medios que se ofrecen en el PEP 3143 o para otros, puede os.execl (u otra función os.exec...) su código de destino - Esto va en dicho código de destino en exactamente el mismo proceso que acabamos de decir se demoniza, y así sigue siendo demonizado, como se desee.

El último paso no se puede utilizar subprocess porque tiene que ejecutar en el mismo proceso (endemoniada), superponiendo su código ejecutable - exactamente lo os.execl y son los amigos.

El primer paso, antes de daemonization, podría concebiblemente ser hecho a través de subprocess, pero eso es algo incómodo (que necesita para poner el código daemonize-entonces-os.exec en una separada .py): más comúnmente usted acaba desea os.fork e inmediatamente daemonize el proceso secundario.

subprocess es bastante conveniente como una forma de plataforma cruzada para ejecutar otros procesos, pero realmente no puede reemplazar el viejo enfoque de "fork y exec" de Unix para usos avanzados (como la demonización, en este caso) - - por eso es bueno que la biblioteca estándar de Python también le permita hacer esto último a través de esas funciones en el módulo os! -)

+0

Gracias. ¿Y podré conocer la identificación del proceso del proceso daemonizado del antiguo proceso? –

+0

La bifurcación doble se encuentra un poco en el camino, por lo que debe comunicarla; por ejemplo, el proceso secundario podría escribir la identificación del proceso del nieto en su 'stdout' (de donde puede obtener el proceso principal) justo después de bifurcado y antes de que termine. Sin embargo, debe crear su propio protocolo, ya que no existe uno establecido en la biblioteca estándar de Python. –

3

Use subprocess módulo. Popen instancias tienen un atributo pid.

+0

Excelente - también estaba buscando esto – wvd

+0

¿No significa esto que mi nuevo proceso será el hijo del proceso de python? ¿Qué pasará cuando termine el proceso de Python? (ver edición). Gracias –

0

Gracias por la ayuda. Esto es lo que hice al final, y parece funcionar bien. El código usa python-daemon. Tal vez debería hacerse algo más inteligente para transferir la identificación del proceso del niño al padre, pero esa es la parte más fácil.

import daemon 
def run_in_background(command, tmp_dir="/tmp"): 

    # Decide on a temp file beforehand 
    warnings.filterwarnings("ignore", "tempnam is a potential security") 
    tmp_filename = os.tempnam(tmp_dir) 

    # Duplicate the process 
    pid = os.fork() 


    # If we're child, daemonize and run 
    if pid == 0: 
     with daemon.DaemonContext(): 
      child_id = os.getpid() 
      file(tmp_filename,'w').write(str(child_id)) 
      sp = command.split(' ') 
      os.execl(*([sp[0]]+sp)) 
    else: 
     # If we're a parent, poll for the new file 
     n_iter = 0 
     while True: 
      if os.path.exists(tmp_filename): 
       child_id = int(file(tmp_filename, 'r').read().strip()) 
       break 

      if n_iter == 100: 
       raise Exception("Cannot read process id from temp file %s" % tmp_filename) 
      n_iter += 1 

      time.sleep(0.1) 

     return child_id 
Cuestiones relacionadas