4 votes

Spawn subprocess qui attend l'entrée de la console sans bloquer ?

J'essaie d'effectuer une connexion CVS à partir de Python en appelant le processus cvs.exe. Lorsque j'appelle cvs.exe manuellement, il affiche un message sur la console et attend que l'utilisateur saisisse son mot de passe.

En l'appelant avec subprocess.Popen, j'ai remarqué que l'appel se bloque. Le code est

subprocess.Popen(cvscmd, shell = True, stdin = subprocess.PIPE, stdout = subprocess.PIPE,
    stderr = subprocess.PIPE)

Je suppose qu'il se bloque parce qu'il attend une entrée, mais je m'attendais à ce que l'appel à Popen renvoie immédiatement et que je puisse ensuite appeler subprocess.communicate() pour entrer le mot de passe réel. Comment puis-je obtenir ce comportement et éviter le blocage de Popen ?

Système d'exploitation : Windows XP
Python : 2.6
cvs.exe : 1.11

2voto

nosklo Points 75862
  • Retirer le shell=True partie. Votre coquille n'a rien à voir avec cela. Utilisation de shell=True est une cause fréquente de problèmes.
  • Utiliser une liste de paramètres pour cmd.

Exemple :

cmd = ['cvs', 
       '-d:pserver:anonymous@bayonne.cvs.sourceforge.net:/cvsroot/bayonne', 
       'login']
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE) 

Cela ne bloque pas sur mon système (mon script continue de s'exécuter). Cependant, étant donné que cvs lit le mot de passe directement depuis le terminal (et non depuis l'entrée ou la sortie standard), vous ne peut pas il suffit d'écrire le mot de passe sur l'entrée du sous-processus.

Ce que vous pouvez faire, c'est passer le mot de passe en tant que partie de la spécification CVSROOT à la place, comme ceci :

:pserver:<user>[:<passwd>]@<server>:/<path>

Par exemple, une fonction permettant de se connecter à un projet Sourceforge :

import subprocess

def login_to_sourceforge_cvs(project, username='anonymous', password=''):
    host = '%s.cvs.sourceforge.net' % project
    path = '/cvsroot/%s' % project
    cmd = ['cvs', 
           '-d:pserver:%s:%s@%s:%s' % (username, password, host, path), 
           'login']
    p = subprocess.Popen(cmd, stdin=subprocess.PIPE, 
                              stdout=subprocess.PIPE
                              stderr=subprocess.STDOUT) 
    return p

Cela fonctionne pour moi. Appeler

login_to_sourceforge_cvs('bayonne')

se connectera anonymement au CVS du projet Bayonne.

0voto

Heikki Toivonen Points 11133

Si vous automatisez des programmes externes qui ont besoin d'être saisis - comme le mot de passe - votre meilleure option serait probablement d'utiliser pexpecter .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X