2011-09-17 4 views
1

Edit: mon code final ressemble à ceci:Python: Spawn processus sudo (en nouveau terminal), attendez terminé

#WARNING: all " in command need to be escaped: \\" 
def spawnInNewTerminal(command): 
    #creates lock file 
    lock = open(lockPath, 'w') 
    lock.write("Currently performing task in separate terminal.") 
    lock.close() 

    #adds line to command to remove lock file 
    command += ";rm " + lockPath 

    #executes the command in a new terminal 
    process = subprocess.Popen (
     ['x-terminal-emulator', '-e', 'sh -c "{0}"'.format(command) ] 
     , stdout=subprocess.PIPE) 
    process.wait() 

    #doesn't let us proceed until the lock file has been removed by the bash command 
    while os.path.exists(lockPath): 
     time.sleep(0.1) 

question d'origine:

Je suis en train d'écrire une simple enveloppe cela installe les paquets manquants "à la volée" avant de finalement lancer LuaLaTeX. Il fonctionne la plupart du temps, mais à la fin, je dois exécuter la commande

sudo tlmgr install [string of packages] 

et, en outre, parce qu'il n'y a aucune garantie de l'éditeur de LaTeX permettra l'entrée d'utilisateur, je dois appeler un nouveau terminal pour faire en sorte qu'ils peut entrer son mot de passe sudo.

J'ai surtout compris cela: soit

process = subprocess.Popen(
    shlex.split('''x-terminal-emulator -t \'Installing new packages\' -e \'sudo tlmgr install ''' + packagesString + '''\''''), stdout=subprocess.PIPE) 
retcode = process.wait() 

ou

os.system('''x-terminal-emulator -t \'Installing new packages\' -e \'sudo tlmgr install ''' + packagesString + '''\'''') 

Le seul problème est, cette ligne n'attend pas que le processus de terminal donné naissance est fait. En fait, il continue à la ligne suivante (exécutant le LuaLaTeX réel) immédiatement, avant que l'utilisateur puisse même entrer leur mot de passe ou télécharger les paquets! D'après ce que je comprends, c'est parce que le processus sudo child finit tout de suite. Y a-t-il un moyen de s'assurer que le processus tlmgr se termine avant de continuer?

Répondre

3

La raison est que l'émulateur x-terminal génère un nouveau processus et se termine, vous ne pouvez donc pas savoir quand la commande exécutée est terminée. Pour contourner cela, une solution serait de modifier votre commande pour ajouter une autre commande qui vous avertit. Puisque l'émulateur x-terminal-émulateur n'exécute jamais qu'une seule commande, nous pouvons utiliser un shell pour les chaîner. Probablement pas la meilleure façon de le faire, mais on serait:

os.system('x-terminal-emulator -t "Installing new packages" -e "sh -c \\"sudo tlmgr install %s; touch /tmp/install_completed\\""' % packagesString) 
while not os.path.exists("/tmp/install_completed"): 
    time.sleep(0.1) 
os.remove("/tmp/install_completed") 
+0

J'essaie quelque chose de similaire, mais il semble que seule la première commande est exécutée lorsque appelé se de cette façon. Cela vous arrive-t-il aussi? – scarlet

+0

Vrai, ne tenait pas compte de cela. J'ai mis à jour la réponse. – rumpel

+0

Réponse très illustrative! – scarlet

Questions connexes