Key press in a Python subprocess? - python

try:
subprocess.run(exe_path)
keyboard.press_and_release('enter')
print('Successful Extracted')
except Exception as exe:
print(exe.args)
keyboard.press_and_release('enter')
The point is to run the EXE of windows but it needs an input of keyboard to end its process, and it will remain stuck over there unless a keyboard input is given physically. Right now I am facing an issue as
subprocess.run('some_exe')
is running the process and after successfully run asking
Press Any Key To Exit
while I have already mentioned next to subprocess.run
keyboard.press_and_release('enter')
and it's coming to the next line unless we press the button from the keyboard manually
NOTE: python3.8

For the sake of a reproducible example, say we want to run the following Python script as a subprocess, let's call it script.py.
input('Press Enter to exit.')
It won't terminate until the user presses the Enter key. If we want to emulate the key press, we can just send a newline character to the subprocess's stdin using Popen.communicate. Like so:
from subprocess import Popen, PIPE
process = Popen(['python', 'script.py'], stdin=PIPE, text=True)
process.communicate('\n')
The external program doesn't have to be a Python script, it can be any executable. Just replace ['python', 'script.py'] with the corresponding command-line call, e.g. ['some_exe'].
Obviously this also works if the external program accepts any key to exit. Only sending special keys which don't have an obvious text representation, such as F1, would complicate things.

You can create a .vbs file to run your .exe file or python script without console debugging window:
Set oShell = CreateObject ("Wscript.Shell")
Dim strArgs
strArgs = "cmd /c python main.py"
oShell.Run strArgs, 0, false
If you have .exe file just replace python main.py with yourFile.exe.

Related

Python freezes running exe file

I'm doing a simple python gui and on button click it will run a simple command:
os.system("C:/cygwin64/bin/bash.exe")
When I look in the console it ran correctly and but my guy freezes and is not responding.
If I run the the command in the console without python it works perfectly and I start cygwin terminal.
If you know what is cygwin is there a better way to start it in the same terminal?
os.system blocks the current thread, you can use os.popen in order to do that in another thread, and it also gives you few methods to detach/read/write etc' that process.
for example,
import os
a = os.popen("python -c 'while True: print(1)'")
will create a new process that will be terminated as soon as you terminate your script.
you can do
for i in a:
print(i)
for example, and it will block the thread as os.system does.
you can a.detach() it whenever you want to terminate the process.
However, os.system
import os
os.system("python -c 'while True: print(1)'")
it will output the 1s forever until you terminate the script.
You can use function Popen in package subprocess. It has many possible arguments that allow you to pipe input to and/or pipe output from the program you are running. But if you just want to execute bash.exe while allowing your original Python program to continue running and eventually wait for the completion of bash.exe, then:
import subprocess
# pass a list of command-line arguments:
p = subprocess.Popen(["C:/cygwin64/bin/bash.exe"])
... # continue executing
# wait for the subprocess (bash.exe) to end:
exit_code = p.wait()

Subprocess.Popen to open an .exe terminal program and input to the program

I am trying to open a .csv file using a .exe file. Both the file and program are contained in the same folder. When manually opening the folder I drag the csv file ontop of the exe, it then opens and I press any key to commence the program.
When using the shell I can do what I want using this script
E:
cd ISAAC\SWEM\multiprocess\2000
SWEM_1_2000_multiprocess.exe "seedMIXsim.csv"
<wait for program to initialize>
<press any key>
So far in python3 I have tried several variations of subprocess, the latest using Popen with an input argument of ="h" as a random key should start the program.
proc = subprocess.Popen(
['E://ISAAC//SWEM//multiprocess//2010//SWEM_1_2010_multiprocess.exe', '"E://ISAAC//SWEM//multiprocess//2010//seedMIXsim.csv"'], input="h")
However, when I input any arguments such as stdout or input, the python program will almost immediately finish without doing anything.
Ideally, I would like to open a visible cmd window while running the program as the exe runs in the terminal and shows a progress bar.
I solved this by replacing // with \ and using proc.communicate to wait until the process finishes. This comes down to the specific design of the C program, which exits with "press any key".
def openFile(swemPath):
simFile =(swemPath +'seedMIXsim.csv').replace('//', '\\')
swemFile = f"E:\ISAAC\preSWEMgen\SWEMfiles\SWEM{cfg.hoursPerSimulation}hour.exe"
proc = subprocess.Popen([swemFile, simFile], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
wait = proc.communicate(input=b" ")

Programmatically injecting command into Python Cmd's cmdloop

Using Python Cmd2 module (inherits from Cmd) to create a MyCmd CLI for my program. In most cases, I am just using my script normally with the built-in commands. The ‘quit’ command is implemented to do some cleanup for the script and subsequently exit. The Cmd2 module waits for input via the raw_input.
In a specific case, I want to programmatically invoke ‘quit’ instead of issuing it at the command line. This is done via a separate thread where a REST API translates a ‘quit’ POST to invoke quit on the main thread of the script.
I found a couple of SO questions that want to do something similar, but not exactly like this. I tried to follow the below example, but it didn’t work:
Python StringIO - selectively place data into stdin
Then I tried something simple. Basically did the below from the thread:
sys.stdin = StringIO('quit\n')
sys.stdin.flush()
It seems that the word 'quit' was injected, but the script would not do its clean exit. However, I could go back to the command line and simply press Enter, which would trigger the cleanup and exit process. Not sure why ‘\n’ was not being interpreted as Enter.
My cmd is simply invoked in the below manner:
mycmd = MyCmd()
mycmd.cmdloop()
How can I properly inject ‘quit’ into the cmdloop of Cmd?
Have you tried the cmd.onecmd("quit") method? I think it can be used to inject commands in the interpreter.

How to get two python processes talking over pipes?

I'm having troubles getting this to work. Basically I have a python program that expect some data in stdin, that is reading it as sys.stdin.readlines() I have tested this and it is working without problems with things like echo "" | myprogram.py
I have a second program that using the subprocess module calls on the first program with the following code
proc = subprocess.Popen(final_shell_cmd,
stderr=subprocess.PIPE, stdout=subprocess.PIPE,
shell=False), env=shell_env)
f = ' '.join(shell_cmd_args)
#f.append('\4')
return proc.communicate(f)
The second program is a daemon and i have discovered that the second program works well as long as I hit ctrl-d after calling it from the first program.
So it seems there is something wrong with subprocess not closing the file and my first program expecting more input when nothing more should be sending.
anyone has any idea how I can get this working?
The main problem here is that "shell_cmd_args" may contain passwords and other sensitive information that we do not want to pass in as the command name as it will show in tools like "ps".
You want to redirect the subprocess's stdin, so you need stdin=subprocess.PIPE.
You should not need to write Control-D ('\4') to the file object. Control-D tells the shell to close the standard input that's connected to the program. The program doesn't see a Control-D character in that context.

Retrieving Raw_Input from a system ran script

I'm using the OS.System command to call a python script.
example:
OS.System("call jython script.py")
In the script I'm calling, the following command is present:
x = raw_input("Waiting for input")
If I run script.py from the command line I can input data no problem, if I run it via the automated approach I get an EOFError. I've read in the past that this happens because the system expects a computer to be running it and therefore could never receive input data in this way.
So the question is how can I get python to wait for user input while being run in an automated way?
The problem is the way you run your child script. Since you use os.system() the script's input channel is closed immediately and the raw_input() prompt hits an EOF (end of file). And even if that didn't happen, you wouldn't have a way to actually send some input text to the child as I assume you'd want given that you are using raw_input().
You should use the subprocess module instead.
import subprocess
from subprocess import PIPE
p = subprocess.Popen(["jython", "script.py"], stdin=PIPE, stdout=PIPE)
print p.communicate("My input")
Your question is a bit unclear. What is the process calling your Python script and how is it being run? If the parent process has no standard input, the child won't have it either.

Categories