0

I'm trying to write a python script that starts a subprocess, and writes to the subprocess stdin. Does some tests on teh output and then writes more commands to stdin.

I have tried:

def get_band():
    print "band" 
    p = subprocess.Popen(["/path/to/program","-c","-"], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)

    ran_stdout = p.communicate(input='show status')[0]
    print(ran_stdout)

However the print statement gives:

Unable to connect at 127.0.0.1, Connection refused. 

I was wondering if i am doing this right? Here is the documentation about the process I'm trying to run. I want to use the last option.

Running the tool from the Linux shell allows additional options, depending on the options given to the command. The options are as follows:

-h Displays help about the command

-c <Filename>  Instead of taking typed commands interactively from a user the commands are read from the named file, i.e. in batch mode. When all commands are processed the CLI session ends automatically.

-c - As above but reads command from Linux stdin. This allows commands to be ‘piped’ to the program.
Paul
  • 5,756
  • 6
  • 48
  • 78
  • 3
    Could the message be generated by the subprocess? – Bogdacutu Apr 09 '13 at 16:15
  • Yes thank you, I am wondering why it would be and how to get permission? If I run the process from a terminal with these parameters it runs fine. – Paul Apr 09 '13 at 16:19

2 Answers2

1

If you could tell us more about that program, maybe someone knowing this program could try to explain better how it works in particular.

Nevertheless, what you describe

starts a subprocess, and writes to the subprocess stdin. Does some tests on teh output and then writes more commands to stdin.

does not match your code.

Your code prints something to our own stdout, displaying band, and then does a "one-shot" communication with the subprocess.

To be clear about that, p.communicate() writes all it gets to the subprocess, closes its stdin and reads out whatever it gets from stdout and stderr.

Thus it is incompatible with what you desire: write, read, write again.

So you'll have to craft that on your own.

If the chunks you write are small enough to be guaranteed to fit into the pipe buffer, it is simple: just write the commands (don't forget the trailing \n) and read.

But be aware! Don't read more than you really have, or your reading might block.

Thus, work with non-blocking IO or with select.select().

If you need more information about the one or other, there are other answers here on SO which cover these subjects. The other day I wrote one which might help you.

Community
  • 1
  • 1
glglgl
  • 89,107
  • 13
  • 149
  • 217
0

This worked for some reason, passing in the command in the same line. Then call this function for every command I want.

  p = subprocess.Popen(["/path/to/program", '-c', '-', cmd_here],
  stdout=subprocess.PIPE) 
  proc_stdout, proc_stderr = proc.communicate()
  proc.wait()
  #print stuff
Paul
  • 5,756
  • 6
  • 48
  • 78
  • If you give the cmd on the cmdline, it may be that you can even omit the `'-c', '-'`. It depends on the called program. Apart from that, if it is ok for you to have a separate subprocess for every issued command, then this is probably the simplest solution. – glglgl Apr 10 '13 at 11:20
  • all right thanks, still accepting your great answer :) Yep it is ok, now I just need to run them in the background as some outputs take 10 minutes to happen. – Paul Apr 10 '13 at 11:22