2010-05-21 6 views
7

Je travaille avec un système de cluster sur Linux (www.mosix.org) qui me permet d'exécuter des tâches et de faire en sorte que le système les exécute sur différents ordinateurs. Les emplois sont fonctionnent comme ceci:Comment dire l'ID de processus dans Python

mosrun ls & 

Cela va créer naturellement le processus et l'exécuter sur l'arrière-plan, retourner l'identifiant du processus, comme ceci:

[1] 29199 

Plus tard, il sera de retour. J'écris une infrastructure Python qui exécuterait des tâches et les contrôlerait. Pour cela, je veux exécuter des tâches en utilisant le programme mosrun comme ci-dessus, et enregistrer l'ID du processus engendré (29199 dans ce cas). Cela ne peut naturellement pas être fait en utilisant os.system ou commands.getoutput, car l'ID imprimé n'est pas ce que le processus imprime pour sortir ... Des indices?

Modifier:

Depuis le script python est destiné uniquement pour exécuter d'abord le script, les scripts doivent durer plus longtemps que le shell python. Je suppose que cela signifie que le processus mosrun ne peut pas être le processus enfant du script. Aucune suggestion?

Merci

+0

Normalement, les processus enfants continuent de s'exécuter lorsque le processus parent est en cours de fonctionnement. –

Répondre

2

On dirait que vous voulez vous assurer que le processus enfant est daemonized - PEP 3143, que je pointe, documente et pointe vers une implémentation de référence pour cela, et pointe également vers d'autres.

Une fois que votre processus (encore en cours d'exécution du code Python) est daemon, que ce soit par les moyens offerts dans PEP 3143 ou d'autres, vous pouvez os.execl (ou toute autre os.exec... fonction) votre code cible - ce Runs ledit code cible en exactement le même processus que nous venons de dire est démonisé, et donc il continue d'être démonisé, comme vous le souhaitez.

La dernière étape ne peut pas utiliser subprocess parce qu'il a besoin de fonctionner en le même processus (daemon), superposant son code exécutable - exactement ce que os.execl et les amis.

La première étape, avant de démonisation, pourrait éventuellement être fait par subprocess, mais c'est un peu gênant (vous devez mettre le code daemonize-then-os.exec dans une .py séparée): le plus souvent que vous voulez voulez juste os.fork et immédiatement daemonize le processus enfant. Il est très pratique pour exécuter d'autres processus, mais il ne peut pas vraiment remplacer la bonne vieille approche "fork and exec" d'Unix pour des utilisations avancées (comme la démonisation, dans ce cas) - - c'est pourquoi c'est une bonne chose que la bibliothèque standard de Python vous permette également de faire la dernière via ces fonctions dans le module os! -)

+0

Merci. Et serai-je capable de connaître l'identifiant de processus du processus démonisé de l'ancien processus? –

+0

La double fourche est un peu gênante, vous devez donc la communiquer - par exemple, le processus fils peut écrire l'ID de processus du petit-fils dans son 'stdout' (où le processus parent peut l'obtenir) juste après fourchu et avant qu'il se termine. Vous devez cependant créer votre propre protocole, car il n'y en a pas dans la bibliothèque Python standard. –

3

utilisation du module subprocess. Les instances Popen ont un attribut pid.

+0

Excellent - était également à la recherche de ce – wvd

+0

Cela ne signifie pas que mon nouveau processus sera le fils du processus python? que se passera-t-il lorsque je terminerai le processus python? (voir modifier). Merci –

0

Merci à tous pour l'aide. Voici ce que j'ai fait à la fin, et semble fonctionner correctement. Le code utilise python-daemon. Peut-être que quelque chose de plus intelligent devrait être fait sur le transfert du processus d'identification de l'enfant au père, mais c'est la partie la plus facile.

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 
Questions connexes