1

I want to use subprocess.Popen or any alternative to spawn a new Terminal window and keep supplying commands to it whose output is displayed in the same terminal window. So far I have tried

import subprocess
i=subprocess.Popen("start cmd /K tree",creationflags=subprocess.CREATE_NEW_CONSOLE,stdin=subprocess.PIPE,stdout=subprocess.PIPE,shell=True)
i.stdin.write(b"echo hi\n")

out=i.stdout.read()
print(out)

However only the first command tree executes and the echo does not executeHere it runs tree and stops there after closing the terminal window Here it runs tree and stops there after closing the terminal window the program ends without executing the echo command

Anonymous
  • 596
  • 1
  • 9
  • 26
  • That is just normal behaviour of CMD and also most other shells. If you supply a command to run, they'll run it and exit. Same would happen if you typed that command into a terminal window, it'd create a new cmd process, run the given command and exit. So this isn't a python issue but an issue with your usage of cmd. – jaaq Nov 02 '21 at 08:59
  • 1
    maybe you should use `pexpect` to start `cmd` without any command and later send commands like `tree`. OR maybe you should use subprocess to start only `cmd` and use `stdint` to send `tree` and other commands. – furas Nov 02 '21 at 09:46

2 Answers2

3

So first, to communicate to an proccess you should use subprocess.communicate() instead of stdin.write. From the docs of subprocess:

Use communicate() rather than .stdin.write, .stdout.read or .stderr.read to avoid deadlocks due to any of the other OS pipe buffers filling up and blocking the child process.

Found here

Second, you can not send multiple commands to the process with subprocess as you expected. For more infos see here.

Third, if you really want to send more commands, you have to use other libraries, for linux you can use pexpect for windows you can use wexpect but both have no recent changes (Either they are not under active development, or they are already perfect ;))

D-E-N
  • 1,242
  • 7
  • 14
0

start cmd seems to break wexpect, but if you only need a new shell, and not a new window, try this, as suggested by @furas and @D-E-N:

import wexpect

print("Wexpect Example:")

# Create the child process
child = wexpect.spawn("cmd.exe")
child.expect_exact(">")

# If you only expect a prompt after each command is complete, this should be fine
list_of_commands = ["tree",
                    "echo hi\n", ]
for c in list_of_commands:
    child.sendline(c)
    child.expect_exact(">")
    print(child.before)

# Exit will close the child implicitly, but I add the explicit child.close() anyway
child.sendline("exit")
child.close()

print("Script complete. Have a nice day.")

Output

Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Try the new cross-platform PowerShell https://aka.ms/pscore6

PS C:\Users\Rob\source\repos\Wexpect> python wexpect.py
Wexpect Example:
tree
Folder PATH listing for volume Windows-SSD
Volume serial number is XXXX-XXXX
C:.
├───folder1
├───folder2
│   ├───sub-folder2.1
│   └───sub-folder2.3
└───folder3

C:\Users\Rob\source\repos\Wexpect
echo hi
hi

C:\Users\Rob\source\repos\Wexpect
Script complete. Have a nice day.
PS C:\Users\Rob\source\repos\Wexpect> 

For brevity, I skipped handling EOF and TIMEOUT errors. Check out the pexpect and wexpect documentation for more ideas.

Good luck coding!

Rob G
  • 673
  • 3
  • 10