Merci aux suggestions utiles ci-dessous:débutant python sous-processus: "erreur d'écriture: Broken pipe"
Il semble donc être fixé quand je
- commandes séparées dans des appels individuels à Popen
- stderr = subprocess.PIPE en tant qu'argument pour chaque chaîne Popen.
Le nouveau code:
import subprocess
import shlex
import logging
def run_shell_commands(cmds):
""" Run commands and return output from last call to subprocess.Popen.
For usage see the test below.
"""
# split the commands
cmds = cmds.split("|")
cmds = list(map(shlex.split,cmds))
logging.info('%s' % (cmds,))
# run the commands
stdout_old = None
stderr_old = None
p = []
for cmd in cmds:
logging.info('%s' % (cmd,))
p.append(subprocess.Popen(cmd,stdin=stdout_old,stdout=subprocess.PIPE,stderr=subprocess.PIPE))
stdout_old = p[-1].stdout
stderr_old = p[-1].stderr
return p[-1]
pattern = '"^85567 "'
file = "j"
cmd1 = 'grep %s %s | sort -g -k3 | head -10 | cut -d" " -f2,3' % (pattern, file)
p = run_shell_commands(cmd1)
out = p.communicate()
print(out)
Original Post:
J'ai passé trop de temps à essayer de résoudre un problème de tuyauterie simple subprocess.Popen.
code:
import subprocess
cmd = 'cat file | sort -g -k3 | head -20 | cut -f2,3' % (pattern,file)
p = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE)
for line in p.stdout:
print(line.decode().strip())
sortie pour le fichier ~ 1000 lignes de longueur:
...
sort: write failed: standard output: Broken pipe
sort: write error
sortie pour le fichier> 241 lignes de longueur:
...
sort: fflush failed: standard output: Broken pipe
sort: write error
sortie pour le fichier < 241 les lignes de longueur sont bien.
J'ai lu les documents et googlé comme un fou mais il y a quelque chose de fondamental au sujet du module de sous-processus qui me manque ... peut-être à faire avec des tampons. J'ai essayé p.stdout.flush() et joué avec la taille de la mémoire tampon et p.wait(). J'ai essayé de reproduire cela avec des commandes comme 'sleep 20; cat moderatefile 'mais cela semble fonctionner sans erreur.
... et p2.communicate() fonctionne également mais je pense que cela peut causer des problèmes si la sortie est grande. – mathtick
'Nouveau code' très utile. J'adore pouvoir utiliser exactement la même commande que j'ai utilisée pour tester dans le shell. Deux suggestions: 1) faire pluriel: run_shell_commands 2) soit supprimer, commenter, ou ajouter debug = false autour des instructions d'impression à l'intérieur de la fonction – PeterVermont
Merci. Ran dans le même problème de tuyau cassé avec des fichiers sur une certaine taille. J'ai utilisé votre code et ça fonctionne comme un charme. – poof