2012-07-12 22 views
18

tengo un guión que quiero correr desde el interior de pitón (2.6.5) que sigue la lógica continuación:Ejecución de un comando interactivo desde dentro pitón

  • Solicitar al usuario la contraseña. Parece ("Ingresar contraseña:") (* Nota: La entrada no se refleja en la pantalla)
  • Información irrelevante de salida
  • Preguntar al usuario por la respuesta ("Blah Blah nombre_archivo.txt blah blah (S/N) ?:")

La última línea de aviso contiene texto que debo analizar (filename.txt). La respuesta proporcionada no importa (el programa en realidad podría salir de aquí sin proporcionar uno, siempre que puedo analizar la línea)

Mis requisitos son un poco similar a Wrapping an interactive command line application in a python script. Tal vez soy un poco grueso, pero las respuestas parecen un poco confusas, y el mío aún se cuelga incluso cuando el OP menciona que no es "para él".

Al mirar a su alrededor, he llegado a la conclusión de que el subproceso es la mejor manera de hacerlo, pero tengo algunos problemas. Popen línea está por debajo de

p = subprocess.Popen("cmd", shell=True, stdout=subprocess.PIPE, 
stderr=subprocess.STDOUT, stdin=subprocess.PIPE) 
  • Cuando llamo una lectura() o readline() en la salida estándar, es el símbolo de la impresora para la pantalla y se cuelga.

  • Si llamo a una escritura ("contraseña \ n") para stdin, el aviso se escribe en la pantalla y se cuelga. El texto en write() no está escrito (el cursor no mueve una nueva línea).

  • Si llamo p.communicate ("contraseña \ n"), mismo comportamiento que el de escritura()

que estaba buscando algunas ideas aquí en la mejor forma de entrada a la entrada estándar y, posiblemente, cómo analizar la última línea de la salida si te sientes generoso, aunque probablemente podría resolverlo eventualmente. ¡Gracias!

+3

Usted debe mirar pexpect: http://www.noah.org/wiki/pexpect –

+0

creo que es necesario escribir en la salida estándar y leer de la entrada estándar ... no es el otherway alrededor como se pone por encima de –

+0

@Joran jaja, sí, lo siento. A eso me refería. – user1521597

Respuesta

10

Si se está comunicando con un programa que genera subprocesos, debe consultar Non-blocking read on a subprocess.PIPE in python. Tuve un problema similar con mi aplicación y encontré que el uso de colas es la mejor manera de hacer comunicación continua con un subproceso.

En cuanto a obtener valores del usuario, siempre puede usar el comando raw_input() incorporado para obtener respuestas, y para las contraseñas, intente utilizar el módulo getpass para obtener contraseñas que no generen eco de su usuario. Luego puede analizar esas respuestas y escribirlas en su subproceso 'stdin.

que terminé haciendo algo parecido a lo siguiente:

import sys 
import subprocess 
from threading import Thread 

try: 
    from Queue import Queue, Empty 
except ImportError: 
    from queue import Queue, Empty # python 3.x 


def enqueue_output(out, queue): 
    for line in iter(out.readline, b''): 
     queue.put(line) 
    out.close() 


def getOutput(outQueue): 
    outStr = '' 
    try: 
     while True: #Adds output from the Queue until it is empty 
      outStr+=outQueue.get_nowait() 

    except Empty: 
     return outStr 

p = subprocess.Popen("cmd", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, universal_newlines=True) 

outQueue = Queue() 
errQueue = Queue() 

outThread = Thread(target=enqueue_output, args=(p.stdout, outQueue)) 
errThread = Thread(target=enqueue_output, args=(p.stderr, errQueue)) 

outThread.daemon = True 
errThread.daemon = True 

outThread.start() 
errThread.start() 

try: 
    someInput = raw_input("Input: ") 
except NameError: 
    someInput = input("Input: ") 

p.stdin.write(someInput) 
errors = getOutput(errQueue) 
output = getOutput(outQueue) 

Una vez que haya las colas de hecho y los hilos comenzado, puede recorrer a través de obtener la entrada del usuario, consiguiendo errores y salida del proceso, y procesarlos y mostrarlos al usuario.

0

Usar el enhebrado puede ser un poco exagerado para tareas simples. En su lugar se puede usar os.spawnvpe. Generará script shell como un proceso. Podrás comunicarte de manera interactiva con el guión. En este ejemplo, pasé la contraseña como argumento, obviamente no es una buena idea.

import os 
import sys 
from getpass import unix_getpass 

def cmd(cmd): 
    cmd = cmd.split() 
    code = os.spawnvpe(os.P_WAIT, cmd[0], cmd, os.environ) 
    if code == 127: 
     sys.stderr.write('{0}: command not found\n'.format(cmd[0])) 
    return code 

password = unix_getpass('Password: ') 
cmd_run = './run.sh --password {0}'.format(password) 
cmd(cmd_run) 

pattern = raw_input('Pattern: ') 
lines = [] 
with open('filename.txt', 'r') as fd: 
    for line in fd: 
     if pattern in line: 
      lines.append(line) 

# manipulate lines 
Cuestiones relacionadas