I have an executable file I want to interface with using Python. When run from PowerShell, the executable prints out a few lines of text, including an IP address and username, and expects the user to respond with the password associated with the given IP address and username. My real use case is a bit more complicated, but let's assume I just want to interact with the executable through Python instead of PowerShell. My Python program should be able to read the output of the executable, relay the IP and username to the user, ask the user for a password, then relay that password back to the executable. However, I get stuck when I try to read from the executable's stdout (see code below). What am I doing wrong? Is there something about Windows executables and Python that I am missing?
Here is what I came up with initially:
import subprocess
import re, os
EXE_PATH = 'C:/path/to/executable.exe'
EXE_DIR = os.path.dirname(EXE_PATH)
def get_next_context(process):
match = None
out = ''
while process.poll() is None:
out += process.stdout.read(1) # Real executable hangs here
match = re.match(r'Host IP: (.+)\nHost User: (.+)\nPassword: ', out)
if match is not None:
return match.group(1), match.group(2)
return None, None
if __name__ == '__main__':
p = subprocess.Popen([NISRA_PATH, '-e'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE,
shell=True, text=True, cwd=NISRA_DIR)
try:
out = ''
while p.poll() is None:
ip, user = get_next_context(p)
if ip is None:
# Process is done and there are no more passwords to accept
break
password = input('Password for host {} and user {}: '.format(ip, user))
p.stdin.write('{}\r\n'.format(password))
if p.poll() is None:
p.stdin.flush()
finally:
p.kill()
And for the sake of completeness, here is a mock program you can compile to test the code with a real executable:
def foo():
print('Host IP: 192.168.1.1')
print('Host User: Admin')
pass1 = input('Password: ')
print('Host IP: 192.168.1.2')
print('Host User: Admin')
pass2 = input('Password: ')
# Do something with the passwords...
print(pass1)
print(pass2)
if __name__ == '__main__':
foo()
Now, I have tested the program with the test executable and the results were as expected. However, the program does not work with the real executable I want to interface with. The real executable hangs on reading from stdout, as commented in the code.