1

I am starting a script in a new PowerShell window from python and I'd like to let that process run in the background, so I can interact with it continuously.

I've tried with the following code:

p = subprocess.Popen(['start powershell.exe', '-File', 'script.ps1']
                    shell    = True,
                    stdin    = subprocess.PIPE,
                    stdout   = subprocess.PIPE,
                    bufsize  = 1,
                    encoding ='utf-8')

p.stdin.write('input1')
p.stdout.readline()
p.stdin.write('input2')
p.stdout.readline()
p.stdin.write('input3')
p.stdout.readline()

But p.stdin.write does nothing. How can I solve this problem?

Lin
  • 33
  • 6
  • 1
    Does this answer your question? [How do I pass a string into subprocess.Popen (using the stdin argument)?](https://stackoverflow.com/questions/163542/how-do-i-pass-a-string-into-subprocess-popen-using-the-stdin-argument) – Maurice Meyer Sep 16 '20 at 10:52
  • https://stackoverflow.com/a/8475367/13824946 –  Sep 16 '20 at 10:55
  • I've already tried with communicate(), but it does not support multiple communication – Lin Sep 16 '20 at 11:19
  • 1
    *"I can interact with it continuously"* - What does that mean? – IInspectable Sep 16 '20 at 13:02
  • @IInspectable like the code says: I have multiple inputs, I want to feed them to the subprocess sequentielly and get the result each time – Lin Sep 16 '20 at 13:16
  • Hi, did my answer help you or any problems, let me know? – Hassan Voyeau Sep 17 '20 at 12:14

1 Answers1

1

I have created a minimal example to understand exactly what you want. From this tell me what you want?

test.py

import subprocess, sys, os

p = subprocess.Popen(['start', 'powershell.exe', '-File', 'H:\Coding\stack\script.ps1'],
                    shell=True,
                    stdout = subprocess.PIPE,
                    stdin = subprocess.PIPE,
                    bufsize = 1,
                    encoding ='utf-8'
                    )

while p.poll() is None:
    output = p.stdout.readline()
    print(output)

print('end of python'))

script.ps1

$input = Read-Host -Prompt 'input'
Write-Host $input
$input = Read-Host -Prompt 'input'
Write-Host $input
$input = Read-Host -Prompt 'input'
Write-Host $input
Write-Host 'end of process'

Write-Host -NoNewLine 'Press any key to continue...';
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown');

Results

PS H:\Coding\stack> python test.py
(new window started)
input: test
test
input: this
this
input: out
out
end of process
Press any key to continue...
(window closed)
end of python
Hassan Voyeau
  • 3,383
  • 4
  • 22
  • 24
  • Thanks for your effort. "start" is missing in front of "powershell.exe" since I need a separate window. I am not using p.communicate() because I have more than one input. – Lin Sep 16 '20 at 13:43
  • In another words, I have more than one "hello" as input, but "hello1", "hello2", "hello3" etc. and I need to process them sequentially – Lin Sep 16 '20 at 13:45
  • @Lin Updated answer – Hassan Voyeau Sep 16 '20 at 14:03
  • 1
    To get a separate console window, you can use `creationflags=subprocess.CREATE_NEW_CONSOLE` with `shell=False` (default) instead of CMD's internal `start` command with `shell=True`. There's no need to spawn a cmd.exe process for this. – Eryk Sun Sep 16 '20 at 20:00
  • Also, an args list shouldn't be used with `shell=True` anyway since subprocess doesn't know how to properly build a command line for cmd.exe (it doesn't use `CommandLineToArgvW` rules). Also, using `start` here is buggy if the path to the script ends up containing spaces since `start` will interpret the first quoted string, in this case the path, as the window title to use. – Eryk Sun Sep 16 '20 at 20:01