Как работать с исполняемым файлом, требующим интерактивных ответов?

1

У меня есть исполняемый файл, называемый tsfoil2.exe, и я хочу использовать этот.exe из моей среды python. Я запускаю Python 2.7.3 с Spyder 2.1.11 в Windows 7.

Для работы с.exe требуется некоторый ввод, жесткий диск по умолчанию ("I: \"), имя для выходного файла ("test") и имя для входного файла ("SC20610.inp"),

Один из моих коллег посоветовал мне использовать os.system и снабдить его временным входным файлом, который содержит все аргументы.

f = open('temp', 'w') 
f.write('I:\ \n') 
f.write('test \n')
f.write('SC20610.inp\n')  
f.close() 

Затем я передаю этот файл аргументам в.exe следующим образом:

os.system("tsfoil2.exe < temp")

Все это работает, но для завершения программы требуется "ВВОД". По какой-то причине.exe неоднократно запрашивает "Нажмите клавишу ENTER, чтобы выйти". Даже когда я нажимаю клавишу ввода в моей Spyder-консоли, программа не прерывается.

Есть ли способ дать ключ "ENTER" в качестве интерактивного входа в.exe? Я попытался использовать класс SendKeys, но по мере того, как программа не заканчивается, она не достигает строки кода, содержащей команду SendKeys. Я также попытался включить его в файл аргументов, но это тоже не сработает.

Кроме того, я также выяснил, что было бы полезно переключиться на команду subprocesses, так как это может дать мне больше команд для выполнения, но я не смог запустить исполняемый файл с входными файлами.

Можно ли предоставить необходимое "ENTER" с помощью os.system или переключиться на подпроцесс, и если да, то как я могу построить метод, подобный os.system("tsfoil2.exe <temp"), я используя сейчас.

Я пробовал это:

import subprocess as sub
f = open('temp', 'w') 
f.write('I:\ \n') 
f.write('test \n')
f.write('SC20610.inp\n')  
f.close() 
proc=sub.Popen(["tsfoil2.exe","temp"], shell=True)

и это

import subprocess as sub
p=sub.Popen('tsfoil2.exe')
p.communicate(input='I:' )

Но программа не отвечает на приведенные аргументы.

MWE:

import os
f = open('temp', 'w') 
f.write('I:\ \n') 
f.write('test \n')
f.write('SC20610.inp\n')  
f.close() 

os.system("tsfoil2.exe < temp")

Обе программы можно найти через http://www.dept.aoe.vt.edu/~mason/Mason_f/tsfoil2.exe, входной файл можно найти по адресу http://www.dept.aoe.vt.edu/~mason/Mason_f/SC20610.inp.

Надеюсь, все ясно, и вы можете мне помочь.

  • 1
    Убедитесь, что у вас есть пустая строка в конце вашего файла.
Теги:
subprocess
os.system

1 ответ

1
Лучший ответ

'Press the ENTER key to exit' означает, что программы ожидают новую строку.

Я не вижу пустой строки в конце temp файла. Кроме того, возможно, вы имели в виду 'I:\\\n' - вам нужно использовать '\\' в строковом литерале Python, если вы хотите \ на выходе.

Вопрос в том, что tsfoil2.exe рассматривает новую tsfoil2.exe например, b'\r\n' или просто b'\n' и где он ожидает ее получения: от stdin (getchar()) или непосредственно с консоли (getch()),

Предполагая, что программа ожидает b'\r\n' от stdin в Windows:

import os
from subprocess import CalledProcessError, Popen, PIPE

cmd = "tsfoil2.exe"
input_data = os.linesep.join(['I:\\', 'test', 'SC20610.inp', os.linesep])
p = Popen(cmd, stdin=PIPE, bufsize=0)
p.communicate(input_data.encode('ascii'))
if p.returncode != 0:
   raise CalledProcessError(p.returncode, cmd)

Как это работает

os.linesep == "\r\n" в Windows. "\n".join(["a", "b"]) == "a\nb".

Каждый процесс может иметь три стандартных потока: stdin, stdout, stderr. В Python они представлены как sys.stdin, sys.stdout, sys.stderr. Вы можете читать входные данные из stdin и записывать в stdout, stderr, например, функция input считывает из stdin и print записи в stdout по умолчанию. stderr может использоваться для записи сообщений об ошибках.

stdin=PIPE сообщает Popen создать канал между родительским процессом, в котором он вызывается, и новым дочерним процессом ("tsfoil2.exe") и перенаправляет подпроцесс "stdin". p.communicate(data) записывает данные в p.stdin, закрывает его и ждет завершения дочернего процесса. p.returncode содержит статус выхода дочернего процесса. Обычно ненулевой статус означает отказ.

Он эмулирует конвейер оболочки, фактически не создавая оболочку:

$ echo input data | tsfoil2.exe

Если вход ожидается с консоли, вы можете попробовать модуль SendKeys или его чистую реализацию Python SendKeys-ctypes:

from SendKeys import SendKeys

SendKeys(r"""
    {LWIN}
    {PAUSE .25}
    r
    C:\Path\To\tsfoil2.exe{ENTER}
    {PAUSE 1}
    I:\{ENTER}
    {PAUSE 1}
    test{ENTER}
    {PAUSE 1}
    SC20610.inp{ENTER}
    {PAUSE 1}
    {ENTER}
""")

Я его не тестировал.

  • 0
    Первое решение сработало! Не могли бы вы уточнить немного о том, как это работает? Я тоже что-то пробовал по этому пути, но не смог заставить его работать. Я также попробовал второе решение, но вместо того, чтобы искать нужный путь с помощью .exe (который является C: \ Users \ THC0LQ \ Desktop \ TSFOIL \ tsfoil2.exe), он ищет rC; ßUsersßTHC0LQßDesktopßTSFOILßtsfoil2.exe, по какой-то причине портит данную строку.
  • 0
    @ROIMaison: я добавил раздел "как это работает". Вы должны использовать литерал необработанной строки для функции SendKeys чтобы избежать неправильной интерпретации обратной косой черты (примечание: r"""...""" ). Введите `\` вручную, если copy-paste пытается вставить похожий символ Unicode вместо обратной косой черты.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню