简体   繁体   中英

Automating cmd program using Python

I have a program.exe that runs on cmd window.

How the program works:

It requires three inputs, one at a time. ie. on cmd window Program.exe program starts, waits for 1st input Input 1 program continues, waits for 2nd input Input 2 program runs and reads information into a csv file Input 3: Exit Input Terminates the program and allow the csv file to be accessed

After which, I have to repeat these steps all over, albeit having to rename the files to be read (which I have already figured out).

Hence, I would like to automate it and let it run automatically since it would take up to hours to fully read the files and I don't want to have to physically exit the program and start it up again.

-- A Beginner in Python

My code currently:

import subprocess
subprocess.Popen('Start cmd /k program.exe && Input 1 && Input 2 && Input 3, shell=True)

However, it only opens a cmd window and starts up the program but doesn't enter the inputs into the program.

Returncodes returns a "None", so it would seem that the Inputs are not being entered as the command: Program.exe does not terminate and hence, the subsequent portions do not start.

I've tried:

import subprocess
subprocess.Popen('Start cmd /k program.exe Input 1 Input 2 Input 3', shell=True)

It will instead run "program.exe Input 1 Input 2 Input 3" as a single string into cmd, causing an error.

and also

code = subprocess.Popen('Start cmd /k program.exe', shell=True)
code.communicate(input=Input 1)

But again, it only opens a cmd window and starts up the program My guess is that because the program does not terminate, nothing after that command gets input. However, I am not really sure how.communicate works and would like some insights into the issue.

Sorry if this might sound foolish. I am a complete novice in Python and only have some experience in Matlab.

I am wondering if there is any way to make the program run automatically and exit when it senses that it have finished running (based on how the program is used).

you could use subprocess.run with inputs separated by new lines

#inputs stored in a list

inputs=['input1','input2','input3']

#calling the subprocess with the inputs

process = subprocess.run(['program.exe'],
          input='\n'.join(inputs), 
          capture_output=True, 
          text=True)

result = process.stdout.split("\n")

There is detailed description on how to use this command with further scopes in the official python website subprocess.run

hope this helps!

Here are an example where I use the process object to pass stdin to subprocess. This example expect that program.exe at some point returns after the three inputs is process - and it then collect any output program.exe generate.

p = subprocess.Popen('./program.exe', stdin = subprocess.PIPE, stdout = subprocess.PIPE)
p.stdin.write(b'input1\n')
p.stdin.write(b'input2\n')
p.stdin.write(b'input3\n')
print(p.communicate())

Update

I converted my batch file into an exe file and this solution does not work either. I think you may be trying to do the impossible. Once the .exe file is executed, the new terminal opens in a new window. When this happens, python loses all communication with the code being executed. I stand defeated:(. I leave here my previous answer in case it is relevant to anyone.

PREVIOUS ANSWER - applicable to.bat files

The subprocess solutions did not work for me, as subprocess interprets the input as just one line, rather than separated inputs. I am testing this with a .bat file, but it should be equivalent for .exe .

What work for me is the following:

install package wexpect with pip install wexpect ( pexpect if Unix system).

In your python script, create a new process using the method spawn :

program = wexpect.spawn(FULL_PATH, encoding='utf-8') 

The object program allows you to interact with the .exe file. Unfortunately you need to enter the full path of your file

List item

.

Now comes the tricky bit, which depends on how your .exe interacts. You need to know which lines come just before you need to enter input. For example, if the line expecting an input is Type any input , you'd do the following:

program.expect('Type any input')
program.sendline('Input 1')

You can do this as many times as necessary. You can check output with print(program.before) .

Example:

---> program.bat :

@echo off
echo Batch Script to take input.
set /p input=Type any input
echo Input is: %input%
set /p input2=Type any input
echo Input is: %input2%
echo Finished

---> script.py

import subprocess


import wexpect
PATH='C:\\path\\to\\bat\\file\\program.bat'
program = wexpect.spawn(PATH, encoding='utf-8')
program.expect('Type any input')
program.sendline('Input 1')
program.expect('Type any input')
print(program.before)
program.sendline('Input 2')
program.expect('Finished')
print(program.before)

This prints:

Input 1
Input is: Input 1

Input 2
Input is: Input 2

Note: Obtaining output

Getting the output is a bit weird as it is done through the program.before string, which stores what came just before the currently executed line , and not the currently executed line . This is why I am printing the output after the next program.expect . It is not the most comfortable way to obtain output, but it is enough for debugging and once your code is working you should not need to worry about it too much!

First Thoughts

import subprocess subprocess.Popen('Start cmd /k program.exe && Input 1 && Input 2 && Input 3, shell=True)

I think you're missing a quote there. I changed it to correct it and it opens the program.exe itself, throws an error as I don't have the "program.exe" you have specified.

import subprocess
subprocess.Popen('Start cmd /k program.exe Input 1 Input 2 Input 3', shell=True)

the corrected code would be:

Also If it is possible, can you explain the nature of program.exe

Contemplation

I think what you are trying to do is add a wait to the program.exe so that it waits for the for the first output to be processed.

You can add a wait with python time.sleep() function in python

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM