Ejecutando un comando interactivo desde Python

Tengo un script que quiero ejecutar desde Python (2.6.5) que sigue la lógica siguiente:

  • Preguntar al usuario por la contraseña. Parece que (“Ingresar contraseña:”) (* Nota: la entrada no se muestra en la pantalla)
  • Salida de información irrelevante.
  • Preguntar al usuario por la respuesta (“Blah Blah filename.txt blah blah (S / N) ?:”)

La última línea de solicitud contiene texto que necesito analizar (nombre de archivo.txt). La respuesta proporcionada no importa (el progtwig podría salir de aquí sin proporcionar uno, siempre que pueda analizar la línea)

Mis requisitos son algo similares a envolver una aplicación de línea de comandos interactiva en una secuencia de comandos de python , pero las respuestas parecen un poco confusas, y las mías aún cuelgan incluso cuando el OP menciona que no lo hace por él.

Al mirar a mi alrededor, he llegado a la conclusión de que el subprocess es la mejor manera de hacer esto, pero tengo algunos problemas. Aquí está mi línea de Popen:

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

Estaba buscando algunas ideas aquí sobre la mejor manera de ingresar a stdin y posiblemente cómo analizar la última línea de la salida si te sientes generoso, aunque probablemente podría resolverlo al final.

Si se está comunicando con un progtwig que genera subprocesos, debe revisar la lectura de no locking en un subproceso . PIPE en python . Tuve un problema similar con mi aplicación y descubrí que el uso de Colas es la mejor manera de hacer una comunicación continua con un subproceso.

En cuanto a obtener valores del usuario, siempre puede usar la función raw_input () incorporada para obtener respuestas, y para las contraseñas, intente usar el módulo getpass para obtener contraseñas sin eco de su usuario. Luego puede analizar esas respuestas y escribirlas en la entrada estándar de su subproceso.

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 realizado las colas y los subprocesos iniciados, puede realizar un ciclo para obtener información del usuario, obtener errores y resultados del proceso, y procesarlos y mostrarlos al usuario.

El uso de subprocesos puede ser un poco excesivo para tareas simples. En su lugar, se puede utilizar os.spawnvpe. Se generará shell shell como un proceso. Podrás comunicarte interactivamente con el script. 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