0

I'm trying to port the following c# code into Python. It firstly defines a new process and then runs a windows prompt command (cmd.exe). After that, it executes a command in the prompt and when an external event occurs, it closes the prompt.

//Start the prompt - when an event occured
Process winShell = new Process();
winShell.StartInfo.FileName = "cmd.exe";
winShell.StartInfo.RedirectStandardInput = true;
winShell.Start();

//Execute a command in the prompt
winShell.StandardInput.WriteLine("cd " + projectDirectory);

//Close it - when an event occured
winShell.StandardInput.Flush();
winShell.StandardInput.Close();
winShell.WaitForExit();

I read that for Python 3 (my version 3.7), It is recommended to use subprocess. Unfortunately, I feel a bit confused about which of the function to use. I found call, run and Popen, but I didn't understand how to use them. I wrote the following lines, but they don't produce any visible result.

import subprocess
subprocess.run(['cmd.exe'])

First of all, I would like that the shell appears and than to write some commands in it. Finally, I want to close it.

eljamba
  • 171
  • 1
  • 2
  • 11

1 Answers1

0

Use subprocess.Popen() like this. Each API matches to the corresponding C# API almost 1:1.

p = subprocess.Popen(['cmd.exe'],
    stdin=subprocess.PIPE, stdout=subprocess.PIPE,
    text=True)
p.stdin.write('dir\n')
p.stdin.close()
print(p.stdout.read())
p.wait()
p.stdout.close()

Other API's such as run(), call(), etc are wrappers for Popen(). For example, the above code is equivalent to this one line.

print(subprocess.run(['cmd.exe'], capture_output=True, text=True, input = 'dir\n').stdout)
relent95
  • 3,703
  • 1
  • 14
  • 17
  • Thank you for your answer. But if I execute only the first instruction (popen), no terminal appears. How it can be so difficult to open a Windows shell? It corresponds to the c# winShell.Start() in my previous code. – eljamba Oct 17 '22 at 16:06
  • Even with the *shell=True* option, no terminal appears. – eljamba Oct 17 '22 at 16:15
  • If you execute ```python.exe```, a terminal will not appear. If you want to see the terminal, execute ```pythonw.exe```. For that, you should blame Windows, not Python. – relent95 Oct 17 '22 at 16:25
  • Your answer is quite unclear. Where I have to execute *pythonw* instead of *python*? I use spyder IDE to run the scripts. – eljamba Oct 18 '22 at 09:31
  • See [this question](https://stackoverflow.com/questions/9705982/pythonw-exe-or-python-exe) and [the reference](https://docs.python.org/3/using/windows.html). See also [this old issue](https://github.com/spyder-ide/spyder/issues/794). – relent95 Oct 18 '22 at 10:04
  • I wasn't able to run Windows cmd with any of the function of the subprocess module. The only way to do that was: *os.system('start /wait cmd /k')*. – eljamba Oct 20 '22 at 09:55
  • The strange thing is that even without using the stdout, as in the following code, it prints the output of the command in Spyder shell. Why? – eljamba Oct 20 '22 at 10:28
  • `p = subprocess.Popen(['cmd.exe'], stdin=subprocess.PIPE, text=True)` `fullName = _filePath + '\\' + _fileName` `p.stdin.write('myProgram.exe' + ' ' + fullName + '\n')` `p.stdin.close()` `p.wait()` – eljamba Oct 20 '22 at 10:29
  • You need to understand the concept of the console in Windows, including the condition that a child process allocates a new console or attaches to the console of the parent process, the subsystem field of the PE executable, the STARTUPINFO parameter of CreateProcess() API, etc. There're plenty of resources on Internet, including SO. You will know why I said 'blame Windows'. – relent95 Oct 20 '22 at 12:05