3

I try to wrap cmd.exe under windows with the following program but it doesn't work , it seems to wait for something and doesn't display anything. Any idea what is wrong here ?

import subprocess

process = subprocess.Popen('cmd.exe', shell=False, stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=None)  
process.stdin.write("dir\r\n")  
output = process.stdout.readlines()  
print output
rypel
  • 4,686
  • 2
  • 25
  • 36
user246456
  • 287
  • 1
  • 5
  • 10

3 Answers3

5

Usually when trying to call command prompt with an actual command, it is simpler to just call it with the "/k" parameter rather than passing commands in via stdin. That is, just call "cmd.exe /k dir". For example,

from os import *
a = popen("cmd /k dir")
print (a.read())

The code below does the same thing, though lacks a string for you to manipulate, since it pipes to output directly:

from subprocess import *
Popen("cmd /k dir")
Brian
  • 25,523
  • 18
  • 82
  • 173
  • +1, the printout is more readable than the what the results I received using the op's code. – Anthony Forloney Jan 08 '10 at 14:47
  • yes that works but what i need is to be able to write an interpreter loop around cmd.exe shell. This is why i wanted to redirect stdin ou stdout . Any idea how to achieve this without forking a shell everytime? – user246456 Jan 08 '10 at 14:56
5
process = subprocess.Popen('cmd.exe /k ', shell=True, stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=None)
process.stdin.write("dir\n")
o,e=process.communicate()
print o
process.stdin.close()

by the way, if your actual task is really to do a directory listing, please use Python's own os module, eg os.listdir(), or glob module... etc. Don't call system commands like that unnecessarily. It makes your code not portable.

ghostdog74
  • 327,991
  • 56
  • 259
  • 343
  • yes i should have been more accurate in my question. As written above the idea is to wrap the shell in a iterp loop( can be cmd.exe as something else bash for inst. ) – user246456 Jan 08 '10 at 15:00
2

This locks up because process.stdout.readlines() reads all output by the process (until it terminates). Since cmd.exe is still running, it keeps waiting forever for it to close.

To fix this, you can start a separate thread to read the process output. This is something you need to do anyway if you don't call communicate(), to avoid possible deadlock. This thread can call process.stdout.readline() repeatedly and handle the data or send it back to the main thread for handling.

interjay
  • 107,303
  • 21
  • 270
  • 254
  • i have been able to do what you suggest but know how to sync input and output? How to be sure that the last command issue has completed before looking at the next command. – user246456 Jan 09 '10 at 00:01
  • I don't think there is a solution that will work 100% for that, since there is no concept of "waiting for next command" for subprocesses. I suppose you can try to detect the cmd.exe prompt, but that's quite a hack and won't always work. – interjay Jan 09 '10 at 14:23