У меня есть код, который запускает CMD внутри Python Он будет запрашивать ввод, отправлять его в CMD и ждать вывода (в том же процессе) Я попробовал приведенный ниже код:
import subprocess
p = subprocess.Popen('cmd.exe', stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdin_copy = os.fdopen(os.dup(sys.stdin.fileno()), sys.stdin.mode)
while True:
cmd = input("$")
p.stdin.write(bytes(str(cmd + "\n").encode("utf-8"))
p.stdin.close()
print(p.stdout.read().decode("utf-8"))
Вывод:
$cd H:\\
Microsoft Windows [Version 10.0.17763.195]
(c) 2018 Microsoft Corporation. All rights reserved.
H:\PythonProjects\DatabaseTest>cd H:\\
H:\>
$cd H:\\MyPython\\
Traceback (most recent call last):
File "H:/PythonProjects/DatabaseTest/c.py", line 6, in <module>
p.stdin.write(bytes(str(cmd + "\n").encode("utf-8")))
ValueError: write to closed file
Process finished with exit code 1
Выполняет первую команду, но выдает ошибку второй раз (после закрытия стандартного ввода)
Я искал везде, но не нашел ничего, связанного с этим
Не могли бы вы объяснить, как использовать два потока для этой работы?
Создайте функцию, которая принимает файл и очередь. Он перебирает f.readline(), пока не прочитает пустую строку. Каждая строка получает put в очереди как кортеж (time.time(), line). Основной поток отправляет команду p.stdin и опрашивает очереди stdout и stderr, пока не получит известный ответ в stdout. Я предлагаю вам запустить оболочку с уникальной подсказкой, которую вы можете идентифицировать, например prompt = 'SPAM_SHELL<{}>'.format(uuid.uuid4());cmd = 'cmd.exe /k prompt {}'.format(prompt.replace('<', '$L').replace('>', '$G')).
Создайте процесс с bufsize=0, чтобы избежать сброса p.stdin. Имейте в виду, что внешние команды, которые вы запускаете через эту оболочку, не должны быть интерактивными, если у них нет возможности отключить буферизацию их вывода, когда стандартные потоки не являются файлами консоли.






Вы закрываете свой конец трубы, и CMD увидит эту сломанную трубу как сигнал к выходу. Решение - не делать этого. Проблема сложнее, чем вы думаете. Вам нужно два потока для построчного чтения в цикле, один для
p.stdoutи один дляp.stderr. Строки вывода должны быть поставлены в очередь и иметь временные метки, чтобы их можно было правильно чередовать в качестве ответов на входные команды, записанные вp.stdin. Кроме того, вы не можете использовать UTF-8. CMD использует кодовые страницы ввода / вывода консоли, если он подключен к консоли, что будет зависеть от того, как вы ее запускаете. По умолчанию консоль использует кодовую страницу OEM.