example español check_output python subprocess stdin

check_output - subprocess python español



Python-¿Cómo paso una cadena en subprocess.Popen(usando el argumento estándar)? (10)

"Aparentemente, un objeto cStringIO.StringIO no se curra lo suficientemente cerca de un archivo duck para adaptarse a subprocess.Popen"

:-)

Me temo que no. La canalización es un concepto de sistema operativo de bajo nivel, por lo que absolutamente requiere un objeto de archivo representado por un descriptor de archivo de nivel de sistema operativo. Su solución es la correcta.

Si hago lo siguiente:

import subprocess from cStringIO import StringIO subprocess.Popen([''grep'',''f''],stdout=subprocess.PIPE,stdin=StringIO(''one/ntwo/nthree/nfour/nfive/nsix/n'')).communicate()[0]

Yo obtengo:

Traceback (most recent call last): File "<stdin>", line 1, in ? File "/build/toolchain/mac32/python-2.4.3/lib/python2.4/subprocess.py", line 533, in __init__ (p2cread, p2cwrite, File "/build/toolchain/mac32/python-2.4.3/lib/python2.4/subprocess.py", line 830, in _get_handles p2cread = stdin.fileno() AttributeError: ''cStringIO.StringI'' object has no attribute ''fileno''

Al parecer, un objeto cStringIO.StringIO no grapa lo suficientemente cerca de un archivo duck para adaptarse a subprocess.Popen. ¿Cómo trabajo alrededor de esto?


Estoy un poco sorprendido de que nadie haya sugerido crear una canalización, que en mi opinión es la forma más sencilla de pasar una cadena a un subproceso:

read, write = os.pipe() os.write(write, "stdin input here") os.close(write) subprocess.check_call([''your-command''], stdin=read)


Estoy usando python3 y descubrí que necesitas codificar tu cadena antes de que puedas pasarla a stdin:

p = Popen([''grep'', ''f''], stdout=PIPE, stdin=PIPE, stderr=PIPE) out, err = p.communicate(input=''one/ntwo/nthree/nfour/nfive/nsix/n''.encode()) print(out)


Hay una solución hermosa si estás usando Python 3.4 o mejor. Use el argumento de input en lugar del argumento stdin , que acepta un argumento de bytes:

output = subprocess.check_output( ["sed", "s/foo/bar/"], input=b"foo", )


Me di cuenta de esta solución:

>>> p = subprocess.Popen([''grep'',''f''],stdout=subprocess.PIPE,stdin=subprocess.PIPE) >>> p.stdin.write(b''one/ntwo/nthree/nfour/nfive/nsix/n'') #expects a bytes type object >>> p.communicate()[0] ''four/nfive/n'' >>> p.stdin.close()

Hay alguno mejor?


Tenga en cuenta que Popen.communicate(input=s) puede dar problemas si s es demasiado grande, ya que aparentemente el proceso principal lo almacenará antes de iniciar el subproceso secundario, lo que significa que necesita "el doble" de memoria utilizada en ese momento (al menos De acuerdo con la explicación "debajo del capó" y la documentación relacionada que se encuentra here ). En mi caso particular, s fue un generador que primero se expandió completamente y luego se escribió en stdin por lo que el proceso principal fue enorme justo antes de que se generara el niño, y no se dejó memoria para ahorcarlo:

File "/opt/local/stow/python-2.7.2/lib/python2.7/subprocess.py", line 1130, in _execute_child self.pid = os.fork() OSError: [Errno 12] Cannot allocate memory


Popen.communicate() :

Tenga en cuenta que si desea enviar datos a la entrada estándar del proceso, debe crear el objeto Popen con stdin = PIPE. De manera similar, para obtener cualquier otra cosa que no sea Ninguno en la tupla de resultados, también debe proporcionar stdout = PIPE y / o stderr = PIPE.

Reemplazo de os.popen *

pipe = os.popen(cmd, ''w'', bufsize) # ==> pipe = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE).stdin

Advertencia Use se comunique () en lugar de stdin.write (), stdout.read () o stderr.read () para evitar interbloqueos debido a que cualquiera de los otros buffers de tuberías del sistema operativo se llenen y bloqueen el proceso secundario.

Entonces tu ejemplo podría ser escrito de la siguiente manera:

from subprocess import Popen, PIPE, STDOUT p = Popen([''grep'', ''f''], stdout=PIPE, stdin=PIPE, stderr=STDOUT) grep_stdout = p.communicate(input=b''one/ntwo/nthree/nfour/nfive/nsix/n'')[0] print(grep_stdout.decode()) # -> four # -> five # ->

En la versión actual de Python 3, puede usar subprocess.run , para pasar la entrada como una cadena a un comando externo y obtener su estado de salida, y su salida como una cadena en una llamada:

#!/usr/bin/env python3 from subprocess import run, PIPE p = run([''grep'', ''f''], stdout=PIPE, input=''one/ntwo/nthree/nfour/nfive/nsix/n'', encoding=''ascii'') print(p.returncode) # -> 0 print(p.stdout) # -> four # -> five # ->


""" Ex: Dialog (2-way) with a Popen() """ p = subprocess.Popen(''Your Command Here'', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=PIPE, shell=True, bufsize=0) p.stdin.write(''START/n'') out = p.stdout.readline() while out: line = out line = line.rstrip("/n") if "WHATEVER1" in line: pr = 1 p.stdin.write(''DO 1/n'') out = p.stdout.readline() continue if "WHATEVER2" in line: pr = 2 p.stdin.write(''DO 2/n'') out = p.stdout.readline() continue """ .......... """ out = p.stdout.readline() p.wait()


from subprocess import Popen, PIPE from tempfile import SpooledTemporaryFile as tempfile f = tempfile() f.write(''one/ntwo/nthree/nfour/nfive/nsix/n'') f.seek(0) print Popen([''/bin/grep'',''f''],stdout=PIPE,stdin=f).stdout.read() f.close()


p = Popen([''grep'', ''f''], stdout=PIPE, stdin=PIPE, stderr=STDOUT) p.stdin.write(''one/n'') time.sleep(0.5) p.stdin.write(''two/n'') time.sleep(0.5) p.stdin.write(''three/n'') time.sleep(0.5) testresult = p.communicate()[0] time.sleep(0.5) print(testresult)