2012-03-12 11 views
6

Próbuję komunikować się z botem czatu w wierszu polecenia z Pythonem za pomocą modułu subprocess. (Http://howie.sourceforge.net/ skompilowany przy użyciu win32 binarny, mam swoje powody!)Python interakcja z podprocesami, dlaczego mój proces działa z Popen.communicate, ale nie Popen.stdout.read()?

to działa:

proc = Popen('Howie/howie.exe', stdout=PIPE,stderr=STDOUT,stdin=PIPE) 
output = proc.communicate() 

Ale Popen.communicate czeka na zakończenie procesu (i wysyła go EOF ?), Chcę mieć możliwość interakcji z nim. Pozorna rozwiązanie tego problemu było odczytać stdout/zapisu stdin tak:

To nie działa:

proc = Popen('Howie/howie.exe', stdout=PIPE,stderr=STDOUT,stdin=PIPE) 
while True: print proc.stdout.readline() 

(Zauważ, że ja faktycznie przy użyciu bardziej skomplikowanego kodu na podstawie http://code.activestate.com/recipes/440554/ ale problem jest to samo.)

Problem polega na tym, że drugie podejście działa idealnie do komunikowania się z cmd, ale kiedy uruchomię chatbota, nic. Więc moje pytanie brzmi, jak to jest inne w przechwytywaniu danych wyjściowych do używania Popen.communicate()?

tj. Mogę użyć drugiego podejścia do korzystania z wiersza poleceń, jak zwykle, dopóki nie uruchomię chatbota, w którym to momencie przestaję otrzymywać dane wyjściowe. Używanie pierwszego podejścia poprawnie wyświetla kilka pierwszych linii wyjścia z bota, ale nie pozwala mi na interakcję z nim.

Odpowiedz

9

Jedną z głównych różnic między nimi jest to, że komenda() zamyka stdin po wysłaniu danych. Nie wiem o konkretnym przypadku, ale w wielu przypadkach oznacza to, że jeśli proces oczekuje na koniec danych wprowadzonych przez użytkownika, otrzyma go, gdy zostanie użyta metoda komunikacji() i nigdy nie otrzyma go, gdy kod zostanie zablokowany read() lub readline().

Spróbuj najpierw dodać Popen.stdin.close() i sprawdź, czy ma to wpływ na twoją sprawę.

+0

Dlaczego dziękuję, zamykanie stdin pozwoliło chatbotowi rozpocząć się dokładnie tak, jak zrobiło to 'Popen.communicate', chociaż teraz mam problem, który muszę być w stanie z nim porozmawiać ... – SudoNhim

+0

Być może twoja aplikacja czyta linię -by-line, w takim przypadku możesz po prostu wysłać pojedyncze linie, aby umożliwić odpowiedź? Jakie jest dokładnie zadanie, które próbujesz osiągnąć? – vmalloc

+0

Ale jak mogę wysłać to wejście, gdy stdin został zamknięty? Chcę być w stanie przesyłać i odbierać wiersz po linii – SudoNhim

3

Jeśli chcesz wejść w interakcję z programem po wysłaniu EOF, zamiast używać Popen.stdin.close(), możesz ręcznie wysłać znak Koniec pliku z linii poleceń, który ma ten sam efekt, ale pozostawia otwarte wejście.

W Pythonie sekwencją ucieczki tej postaci jest '\x1a'.