17

I am using the subprocess module to call an external program (plink.exe) to log-in to a server; but when I call communicate to read the output, it is blocking. The code is below:

 import subprocess
 process = subprocess.Popen('plink.exe hello@10.120.139.170 -pw 123456'.split(), shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 print process.communicate() #block here

I know the block is because plink.exe it still running; but I need to read the output before the subprocess terminates. Is there anyway to do that?

Mohsen Nosratinia
  • 9,756
  • 1
  • 25
  • 49
Mingo
  • 1,583
  • 2
  • 15
  • 19
  • Do you need to interact with plink, or you just need to make the call and read the std output without blocking? – Khelben Jan 25 '10 at 15:42
  • related: [Python: read streaming input from subprocess.communicate()](http://stackoverflow.com/q/2715847/4279) – jfs May 09 '15 at 14:14

3 Answers3

32

The whole purpose of the communicate method is to wait for the process to finish and return all the output. If you don't want to wait, don't call communicate. Instead, read from the stdout or stderr attribute to read the output.

If the process outputs to both stdout and stderr (and you want to read it separately), you will have to be careful to actually read from both without blocking, or you can deadlock. This is fairly hard on Windows, and you may wish to use the pexpect module instead.

Björn Pollex
  • 70,106
  • 28
  • 177
  • 265
Thomas Wouters
  • 118,131
  • 21
  • 139
  • 118
  • `pexpect` doesn't work on Windows. [`asyncio`](http://stackoverflow.com/a/20697159/4279) or [threads](http://stackoverflow.com/a/4896288/4279) could be used to read both streams without blocking. – jfs May 09 '15 at 14:13
0

I faced a similar situation where I had to execute a single command lmstat -a and then get the output of the terminal.

If you just need to run a single command and then read the output, you can use the following code:

import subprocess

Username = 'your_username'
Password = 'your_password'
IP = 'IP_of_system'
Connection_type = '-ssh' #can have values -ssh -telnet -rlogin -raw -serial

p = subprocess.Popen(['plink', Connection_type, '-l', Username, '-pw', Password, IP], \
                     shell = False, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
out, err = p.communicate('lmstat -a\nexit\n'.encode())
print(out.decode())
Pulimon
  • 1,706
  • 3
  • 28
  • 44
0

Maybe because "plink.exe" needs to take in input arguments, if you don't pass them, it will block until data are given, you could try adding arguments in method communicate(input)