2010-06-17 13 views
22

Ce n'est pas la première fois que j'ai ce problème, et ça me dérange vraiment. Chaque fois que je ouvre un tuyau à l'aide du module Python subprocess, je ne peux communicate avec elle une fois, que la documentation précise: Read data from stdout and stderr, until end-of-file is reachedCommuniquer plusieurs fois avec un processus sans casser le tuyau?

proc = sub.Popen("psql -h darwin -d main_db".split(),stdin=sub.PIPE,stdout=sub.PIPE) 
print proc.communicate("select a,b,result from experiment_1412;\n")[0] 
print proc.communicate("select theta,zeta,result from experiment_2099\n")[0] 

Le problème ici est que la deuxième fois, Python est pas heureux. En effet, il a décidé de fermer le fichier après la première communication:

Traceback (most recent call last): 
File "a.py", line 30, in <module> 
    print proc.communicate("select theta,zeta,result from experiment_2099\n")[0] 
File "/usr/lib64/python2.5/subprocess.py", line 667, in communicate 
    return self._communicate(input) 
File "/usr/lib64/python2.5/subprocess.py", line 1124, in _communicate 
    self.stdin.flush() 
ValueError: I/O operation on closed file 

Les communications multiples sont-elles autorisées?

+0

pour psql, il existe de nombreux wrappers Python existants: http://wiki.python.org/moin/PostgreSQL –

Répondre

18

Je pense que vous comprenez mal communiquer ...

http://docs.python.org/library/subprocess.html#subprocess.Popen.communicate

envoie une chaîne communiquer à l'autre processus, puis les attend à la fin ... (Comme vous l'avez dit attend l'EOF écouter la stdout & stderror)

Ce que vous devez faire à la place:

proc.stdin.write('message') 

# ...figure out how long or why you need to wait... 

proc.stdin.write('message2') 

(et si yo u besoin d'obtenir le stdout ou stderr vous utiliseriez proc.stdout ou proc.stderr)

+0

J'ai réalisé que vous pourriez vouloir regarder @ http://stackoverflow.com/questions/375427/non-blocking -read-on-a-stream-in-python (C'est un problème très similaire) –

+1

Oui, en effet, j'avais besoin de lectures non bloquantes, car l'écriture pouvait toujours dépendre de ce qui était lu. – Manux

4

J'ai déjà eu ce problème, et pour autant que je pourrais jamais figurer, vous ne pourriez pas faire cela avec subprocess (qui, je suis d'accord, est très contre-intuitif si vrai). J'ai fini par utiliser pexpect (disponible auprès de PyPI).

1

Vous pouvez utiliser:

proc.stdin.write('input')  
if proc.stdout.closed: 
    print(proc.stdout) 
1

Vous pouvez simplement effectuer un seul appel de communicate():

query1 = 'select a,b,result from experiment_1412;' 
query1 = 'select theta,zeta,result from experiment_2099;' 
concat_query = "{}\n{}".format(query1, query2) 
print(proc.communicate(input=concat_query.encode('utf-8'))[0]) 

Le point clé ici est que vous écrivez seulement une fois à stdin, et \n servir de FDL. votre sous-processus psql lit de stdin jusqu'à \n, puis après la fin de la première requête, il passe à nouveau stdin, temps au bout duquel seule la deuxième chaîne de requête est laissée dans le tampon.

+0

Merci, vous avez raison. Actualisé. – zimplex

+0

Ceci tamponne l'intégralité de l'entrée en mémoire, ce qui rend la solution moins qu'idéale pour les situations où l'E/S en continu est souhaitée. – weaver