español - subprocess python 3 example
enlaza varios comandos de Popen con tuberías (4)
Sé cómo ejecutar un comando usando cmd = subprocess.Popen y luego subprocess.communicate. La mayoría de las veces utilizo una cadena tokenizada con shlex.split como argumento ''argv'' para Popen. Ejemplo con "ls -l":
import subprocess
import shlex
print subprocess.Popen(shlex.split(r''ls -l''), stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE).communicate()[0]
Sin embargo, las tuberías parecen no funcionar ... Por ejemplo, el siguiente ejemplo vuelve a señalar:
import subprocess
import shlex
print subprocess.Popen(shlex.split(r''ls -l | sed "s/a/b/g"''), stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE).communicate()[0]
¿Me puede decir lo que estoy haciendo mal, por favor?
Gracias
"" "¿Por qué no usas shell?
"" "
def output_shell (línea):
try:
shell_command = Popen(line, stdout=PIPE, stderr=PIPE, shell=True)
except OSError:
return None
except ValueError:
return None
(output, err) = shell_command.communicate()
shell_command.wait()
if shell_command.returncode != 0:
print "Shell command failed to execute"
return None
return str(output)
Creo que quiere crear una instancia de dos objetos Popen separados aquí, uno para ''ls'' y el otro para ''sed''. Querrá pasar el primer atributo stdout
del objeto Popen como argumento stdin
al segundo objeto Popen.
Ejemplo:
p1 = subprocess.Popen(''ls ...'', stdout=subprocess.PIPE)
p2 = subprocess.Popen(''sed ...'', stdin=p1.stdout, stdout=subprocess.PIPE)
print p2.communicate()
Puedes seguir encadenando de esta manera si tienes más comandos:
p3 = subprocess.Popen(''prog'', stdin=p2.stdout, ...)
Consulte la documentación del subproceso para obtener más información sobre cómo trabajar con subprocesos.
He hecho una pequeña función para ayudar con la tubería, espero que ayude. Cadena Popens según sea necesario.
from subprocess import Popen, PIPE
import shlex
def run(cmd):
"""Runs the given command locally and returns the output, err and exit_code."""
if "|" in cmd:
cmd_parts = cmd.split(''|'')
else:
cmd_parts = []
cmd_parts.append(cmd)
i = 0
p = {}
for cmd_part in cmd_parts:
cmd_part = cmd_part.strip()
if i == 0:
p[i]=Popen(shlex.split(cmd_part),stdin=None, stdout=PIPE, stderr=PIPE)
else:
p[i]=Popen(shlex.split(cmd_part),stdin=p[i-1].stdout, stdout=PIPE, stderr=PIPE)
i = i +1
(output, err) = p[i-1].communicate()
exit_code = p[0].wait()
return str(output), str(err), exit_code
output, err, exit_code = run("ls -lha /var/log | grep syslog | grep gz")
if exit_code != 0:
print "Output:"
print output
print "Error:"
print err
# Handle error here
else:
# Be happy :D
print output
shlex
solo divide espacios de acuerdo con las reglas de shell, pero no trata con pipes.
Sin embargo, debería funcionar de esta manera:
import subprocess
import shlex
sp_ls = subprocess.Popen(shlex.split(r''ls -l''), stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
sp_sed = subprocess.Popen(shlex.split(r''sed "s/a/b/g"''), stdin = sp_ls.stdout, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
sp_ls.stdin.close() # makes it similiar to /dev/null
output = sp_ls.communicate()[0] # which makes you ignore any errors.
print output
de acuerdo con la help(subprocess)
''s
Replacing shell pipe line
-------------------------
output=`dmesg | grep hda`
==>
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]
HTH