Как снова открыть закрытый подпроцесс stdin?

У меня есть код, который запускает 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

Выполняет первую команду, но выдает ошибку второй раз (после закрытия стандартного ввода)

Я искал везде, но не нашел ничего, связанного с этим

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

Eryk Sun 24.12.2018 09:28

Не могли бы вы объяснить, как использовать два потока для этой работы?

Priyansh Anand 24.12.2018 09:39

Создайте функцию, которая принимает файл и очередь. Он перебирает 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')).

Eryk Sun 24.12.2018 17:32

Создайте процесс с bufsize=0, чтобы избежать сброса p.stdin. Имейте в виду, что внешние команды, которые вы запускаете через эту оболочку, не должны быть интерактивными, если у них нет возможности отключить буферизацию их вывода, когда стандартные потоки не являются файлами консоли.

Eryk Sun 24.12.2018 17:39
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
4
750
0

Другие вопросы по теме