Python, ¿tratando de obtener información del subproceso?
Frecuentes
Visto 1,508 veces
4
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.
4 Respuestas
4
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
1
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
0
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
0
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 python multiprocessing subprocess or haz tu propia pregunta.
Relacionado: stackoverflow.com/questions/375427/… - ChristopheD
Estoy abierto incluso a usar cosas de C ++ para que esto funcione. ¿Cómo lo hace IDLE.py? - user1357159