2012-07-12 9 views
18

Ho uno script che voglio correre dall'interno python (2.6.5), che segue la logica di seguito:esecuzione di un comando interattivo all'interno di pitone

  • utente Chiedi la password. Assomiglia ("Inserisci password:") (* Nota: l'input non viene visualizzato sullo schermo)
  • Uscita informazioni irrilevanti
  • Richiedi all'utente risposta ("Blah Blah nomefile.txt blah blah (Y/N) ?:"

L'ultima riga di prompt contiene testo che ho bisogno di analizzare (nomefile.txt). La risposta fornita non importa (il programma potrebbe effettivamente uscire qui senza fornire uno, finché posso analizzare la riga)

miei requisiti sono in qualche modo simile aWrapping an interactive command line application in a python script. Forse sono solo un po 'spessa, ma le risposte sembrano un po' confuse, e la mia ancora si blocca anche quando l'OP dice che non lo fa per lui.

Guardandosi intorno, sono giunto alla conclusione che il sottoprocesso è il modo migliore per farlo, ma ho alcuni problemi. Linea popen è al di sotto

p = subprocess.Popen("cmd", shell=True, stdout=subprocess.PIPE, 
stderr=subprocess.STDOUT, stdin=subprocess.PIPE) 
  • Quando chiamo un read() o readline() su stdout, la richiesta è la stampante allo schermo e si blocca.

  • Se chiamo una scrittura ("password \ n") per stdin, il prompt viene scritto sullo schermo e si blocca. Il testo in write() non è scritto (io non il cursore muove una nuova riga).

  • Se chiamo p.communicate ("password \ n"), stesso comportamento di write()

ero alla ricerca di un paio di idee qui sul modo migliore per essere immessi in stdin e, eventualmente, come analizzare l'ultima riga dell'output se si sente generoso, anche se probabilmente potrei capirlo alla fine. Grazie!

+3

Si dovrebbe guardare pexpect: http://www.noah.org/wiki/pexpect –

+0

Penso che è necessario scrivere su stdout e leggere dallo standard input ... non l'otherway in giro come si mette sopra –

+0

@Joran haha ​​si, mi dispiace. Ecco cosa intendevo. – user1521597

risposta

10

Se si comunica con un programma che sottopone a elaborazione i processi, è necessario controllare Non-blocking read on a subprocess.PIPE in python. Ho avuto un problema simile con la mia applicazione e ho scoperto che usare le code era il modo migliore per fare comunicazioni continue con un sottoprocesso.

quanto per ottenere valori da parte dell'utente, si può sempre utilizzare il raw_input() incorporato per ottenere risposte, e per le password, provare a utilizzare il modulo getpass per ottenere le password non facendo eco dal vostro utente. È quindi possibile analizzare tali risposte e scriverle nello stdin del sottoprocesso.

ho finito per fare qualcosa di simile a quanto segue:

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 volta che avete le code fatti e le discussioni iniziate, è possibile scorrere avere un input da parte dell'utente, ottenendo gli errori e in uscita dal processo, e elaborandoli e mostrandoli all'utente.

0

Utilizzare il threading potrebbe essere un po 'eccessivo per compiti semplici. È possibile utilizzare os.spawnvpe. Spaccherà la shell di script come un processo. Sarai in grado di comunicare in modo interattivo con lo script. In questo esempio ho passato la password come argomento, ovviamente non è una buona 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 
Problemi correlati