Python - Kør et simpelt kommandolinjeprogram med anmodning om I/O og 'proxy' på Windows

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har et simpelt kommandolinje-binært program hello, som udsender til STDOUT:


What is your name?


og venter på, at brugeren indtaster den. Efter at have modtaget deres input, går det ud:


Hello, [name]!


og ophører.


Jeg vil bruge Python til at køre beregninger på det endelige output af dette program ("Hello, [name]!"), men før den endelige udgave vil jeg have Python-scriptet til i det væsentlige at være 'det' det binære program. Med andre ord vil jeg gerne Python sende alle beskeder til STDOUT og derefter acceptere brugerens input og give det til programmet. Jeg vil dog skjule det endelige output, så jeg kan behandle det og vise mine egne resultater til brugeren. Jeg ønsker ikke at replikere hello s adfærd i scriptet, da dette enkle program er et stand-in til et mere komplekst program, som jeg faktisk arbejder med.


Jeg håbede, at der ville være en slags mekaniker i subprocess hvor jeg kunne gøre noget beslægtet med:


while process.is\_running():
    next\_char = process.stdout.read(1)
    if next\_char == input\_prompt\_thing: # somehow check if the program is waiting for input
        user\_input = raw\_input(buffer)
        process.stdin.write(user\_input)
    else:
        buffer += next\_char


Jeg har spillet med subprocess og har i det væsentlige kunnet forstå, at jeg kunne bruge process.stdout.read(1) til at læse fra programmet, før det begyndte at blokere, men jeg kan ikke regne ud, hvordan man slår denne loop før processen blokerer mit Python-script. Jeg er ikke så fortrolig med konsol I/O, og det er ikke et område med stor ekspertise for mig, så jeg begynder at føle mig ret tabt. Jeg sætter pris på enhver hjælp!

Bedste reference


Du kan prøve winpexpect (ikke testet): [12]


import re
from winpexpect import winspawn

p = winspawn('hello')
prompt = "What is your name?"
p.expect(re.escape(prompt))
name = raw\_input(prompt)
p.sendline(name)
p.expect("Hello, .*!")
output = p.after
# ...