0

I usually run a program from my OpenSuse linux terminal by typing ./run file_name. This will bring up a series of options that I can choose from by typing a numeric value 0-9 and hitting return on my keyboard. Now I want to do this from a python script automatically. My example below is not working, but I can't understand where I'm failing and how to debug:

import subprocess
p = subprocess.Popen(["/path/to/program/run", file_name], stdin = subprocess.PIPE,stdout=subprocess.PIPE,shell=False)
print "Hello"
out, err = p.communicate(input='0\r\n')
print out
print err
for line in p.stdout.readlines():
    print line

The output of this program is just

>> Hello
>>

i.e. then it seems to freeze (I have no idea whats actually happening!) I would have expected to see what I see when I run ./run file_name and hit 0 and then return directly in my terminal, but I assure you this is not the case. What can I do to debug my code?

Edit 1: as suggested in comments

import subprocess

fileName = 'test_profile'
p = subprocess.Popen(["/path/to/program/run", fileName], stdin = subprocess.PIPE,stdout=subprocess.PIPE,shell=False)
print "Hello"

for line in iter(p.stdout.readline,""):
    print line

will indeed return the stdout of my program!

Dipole
  • 1,840
  • 2
  • 24
  • 35
  • Yes, it prints out `Hello` and then just waits... – Dipole Feb 15 '16 at 18:41
  • Use `for line in iter(p.stdout.readline,"")` to get output in real time, if you want to continually communicate you will need to change your logic – Padraic Cunningham Feb 15 '16 at 18:42
  • I get nothing from that either! – Dipole Feb 15 '16 at 18:47
  • So you wrote to stdin and then looped not using communicate? – Padraic Cunningham Feb 15 '16 at 18:50
  • 1
    `for line in iter(p.stdout.readlines,"")` is not what was suggest in the comments, `readlines` is not `readline` – Padraic Cunningham Feb 15 '16 at 18:54
  • 1
    Have you tried using `0\n` rather than `\0\r\n`? – zondo Feb 15 '16 at 18:56
  • remove the communicate and use the loop as suggested, use `p.stdin.write`to write. If you want to run simulate many inputs you will also have to check the output and write the appropriate input in the for loop. – Padraic Cunningham Feb 15 '16 at 18:58
  • Thanks for suggestions - so as @PadraicCunningham suggests my stdout from program is at least printing. Is there something bad about using `communicate`? Because I need to enter a sequence of numeric inputs to my program and then exit the program each time I do this in python... – Dipole Feb 15 '16 at 19:00
  • @Jack, communicate is waiting for your program to terminate and you program is waiting for input to continue so you have a stalemate. You are trying to do what pexpect does, it is possible using Popen but you have to write the logic in the order you expect things to happen, http://stackoverflow.com/questions/33088339/input-command-doesnt-seem-to-work-when-used-with-popen-python/33089342#33089342 – Padraic Cunningham Feb 15 '16 at 19:01
  • @zondo So your suggestion actually ended up being the solution. Do you know why `\r` is not necessary? – Dipole Feb 15 '16 at 23:57
  • I'm not sure, but every time I have read files in Python, `\n` has always been the only character at the end. – zondo Feb 16 '16 at 00:58

1 Answers1

1

communicate waits for the completion of the program. For example:

import subprocess
p = subprocess.Popen(["cut", "-c2"], stdin=subprocess.PIPE, stdout=subprocess.PIPE,shell=False)
out, err = p.communicate(input='abc')
print("Result: '{}'".format(out.strip()))

# Result: 'b'

It sounds like you have a more interactive script, in which case you probably should try out pexpect

import pexpect

child = pexpect.spawn('cut -c2')
child.sendline('abc')
child.readline() # repeat what was typed
print(child.readline()) # prints 'b'
CasualDemon
  • 5,790
  • 2
  • 21
  • 39
  • 1
    Wow, i didn't know pexpect. My module of the month. – MaxNoe Feb 15 '16 at 19:07
  • Ok yes thank you for the clarification. I need to send a sequence of inputs all corresponding to typing a number followed by return, and I know these before hand. I don't have access to `pexpect` unfortunately although it looks like what I need. – Dipole Feb 15 '16 at 19:13