Python, ¿tratando de obtener información del subproceso?

main.py

import subprocess,sys
process = subprocess.Popen([sys.executable]+['example.py'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

while True:
    out = process.stdout.read(1)
    if not out:
        out=process.stderr.read(1)
    if out == '' and process.poll() != None:
        break
    if out != '':
        print out

ejemplo.py

f=raw_input('WHats your favorite animal')

Ok, me pregunto cómo puedo verificar la entrada en mi ciclo principal y poder darle algunos datos. En este momento, mi programa se congela cuando uso raw_input.

Esto es lo que me gustaría

while True:
    out = process.stdout.read(1)
    if not out:
        out=process.stderr.read(1)
    if out == '' and process.poll() != None:
        break
    #showing what i want
    if request_input==True:
        give_input('cat') #Give input to the raw_input
    #
    if out != '':
        print out

No sé si hay una característica como esta. Si necesita más explicación por favor comente.

preguntado el 12 de junio de 12 a las 22:06

Estoy abierto incluso a usar cosas de C ++ para que esto funcione. ¿Cómo lo hace IDLE.py? -

4 Respuestas

Esta no es realmente la mejor manera de tener comunicación entre procesos, le recomiendo que use las bibliotecas de subprocesos o multiprocesamiento con algo como una Cola o PIPE para comunicación y sincronización.

una cola sería la forma más sencilla de compartir datos, un proceso pondría un valor y otro obtendría los valores.

Modifiqué su código original para que funcione ahora, tenga en cuenta que raw_input no vacía stdout como tal si no hay nada allí, se bloqueará, http://code.activestate.com/lists/python-list/265749/ es por eso que su código solo estaba esperando la salida estándar ...

ESTO ES PELIGROSO, puede generar interbloqueos, utilícelo bajo su propio riesgo, pruebe con otro método.

import sys
print 'Whats your favorite animal\n' #raw_input doesn't flush :( and we want to read in a whole line
sys.stdout.flush()
f = raw_input()
print f

y el correspondiente main.py

import subprocess, sys, os
process = subprocess.Popen([sys.executable]+['example.py'],
     stdout = subprocess.PIPE, stderr = subprocess.PIPE, stdin = subprocess.PIPE)

while True:
    if process.poll() != None:
        break
    request_input = process.stdout.readline() # read line, this will wait until there's actually a line to read.
    if request_input == "Whats your favorite animal\n":
        print 'request: %s sending: %s' % (request_input, 'cat')
        process.stdin.write('cat\n')
       process.stdin.flush()

Respondido el 13 de junio de 12 a las 00:06

"request_input == "Cuál es tu animal favorito\n":", solo estoy buscando el caso general cuando se ha accedido a la función raw_input. - user1357159

Veo que es un poco más complicado ya que lo que normalmente hace raw_input es simplemente leer desde stdin llamando a readline en ese objeto descriptor de archivo, estaba pensando en verificar si ese archivo se ha abierto, pero creo que se abre automáticamente, tan pronto como comienza la ejecución :( lo siento multiprocesamiento/subprocesamiento quizás lo mejor a menos que realmente necesite raw_input... - Samy Vilar

Ah, ya veo, estoy abierto a cualquier solución. Lo que estoy tratando de hacer es un IDE de Python (por diversión). La entrada en un ide es un poco importante, así que la necesitaría. Supongo que seguiré buscando la respuesta. Nuevamente, gracias por responder. user1357159

no hay problema, interesante, el mejor IDE de python que he usado es pycharm aunque no es gratis, es genial, puedes echarle un vistazo y tal vez obtener algunas ideas :) - Samy Vilar

@ user1357159 Estoy revisando el código fuente de Python, te dejaré. - Samy Vilar

Edit: Parece que no entendí bien tu pregunta, lo siento.

Esto no es tan fácil como podrías pensar:

Tienes que usar select para comprobar si hay datos disponibles en stdin, si hay datos, ¡léelos!

Ejemplo mínimo:

STDIN, STDOUT = 0, 1

while not process.poll() is None:
    out = process.stdout.read(1)

    if not out:
        break

    try:
        fds = select.select([STDIN], [], [])[0]
    except select.error:
        pass
    else:
        if STDIN in fds:
            data = os.read(STDIN, 1024)

            if data_requested:
                process.stdin.write(data)

Información para seleccionar: http://docs.python.org/library/select.html#module-select, http://linux.die.net/man/2/select y http://en.wikipedia.org/wiki/Select_(Unix)

No estoy seguro de si esto funcionará en Windows, ya que Windows solo admite select en enchufes. Pregunta relevante sobre SO: ¿Cuál es el mejor equvalor epoll / kqueue / select en Windows?

contestado el 23 de mayo de 17 a las 13:05

Trate de usar el módulo de multiprocesamiento

from multiprocessing import Process, Value, Array

def f(n, a):
    n.value = 3.1415927
    for i in range(len(a)):
        a[i] = -a[i]

if __name__ == '__main__':
    num = Value('d', 0.0)
    arr = Array('i', range(10))

    p = Process(target=f, args=(num, arr))
    p.start()
    p.join()

    print num.value
    print arr[:]

Respondido el 20 de junio de 12 a las 22:06

A menos que insista en "Python sin procesar", lo mejor es usar el módulo pexpect. He agregado una salida a su ejemplo.py, de lo contrario, no es nada divertido.

Aquí está ejemplo.py:

    f=raw_input('WHats your favorite animal')
    print f.upper()

Aquí está pexpect-example.py que está buscando:

    # see http://pexpect.sourceforge.net/pexpect.html
    import pexpect

    PY_SCRIPT = 'example.py'

    child = pexpect.spawn('python %s' % PY_SCRIPT)

    child.expect ('WHats your favorite animal')

    # comment out these three lines if you run unmodified example.py script
    child.setecho(False)
    child.sendline ('cat')
    print PY_SCRIPT, 'said:', child.readline()

Respondido el 22 de junio de 12 a las 17:06

No necesita la llamada print f.upper(): abb solo estaba agregando eso para mostrar la salida para confirmar que el script funcionó. La parte importante de la respuesta, el módulo pexpect, es casi con certeza la solución más robusta. - dimo414

Lo siento, acabo de hojear la respuesta. Lo he investigado y está bien, pero solo funciona en Linux debido a los módulos que usa pexpect. - user1357159

Además, usar "child.expect ('¿Cuál es tu animal favorito')" no funcionará para mí porque estoy buscando cualquier caso raw_input: user1357159

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.