#python #subprocess #windows-subsystem-for-linux
Вопрос:
Я установил WSL(Ubuntu), и теперь я хочу получить доступ к fish из WSL и выполнить команду, такую как дата из него. Как я могу это сделать?
Вот моя попытка!
import subprocess
subprocess.run(["wsl", "fish"], shell=True)
subprocess.run(["date"], shell=True)
Вывод показывает выполнение до 2-й строки кода, но не выполнение команды date в терминале fish. Есть какое-нибудь решение для этого?
Комментарии:
1. Вы используете это из Windows Python или WSL?
2. Я использую Windows python.
Ответ №1:
Предполагая, что вы просто хотите захватить выходные данные, наиболее эффективным вызовом должен быть:
cp = subprocess.run(["wsl", "-e", "date"], capture_output=True)
date = cp.stdout
Указав -e
, вы полностью пропускаете оболочку, что позволяет избежать накладных расходов при запуске оболочки.
Если вы действительно хотите заставить его работать внутри fish
:
cp = subprocess.run(["wsl", "-e", "fish", "-c", "date"], capture_output=True)
date = cp.stdout
Более подробно:
Если fish
это ваша оболочка по умолчанию, то вам действительно не нужно указывать ее в качестве аргумента для wsl
команды. Вы можете убедиться в этом, выполнив следующие действия в PowerShell или CMD:
wsl ps -eH
PID TTY TIME CMD
1 ? 00:00:00 init
21 ? 00:00:00 init
22 ? 00:00:00 init
23 pts/0 00:00:00 fish
30 pts/0 00:00:00 ps
Обратите внимание, что ps
команда, хотя и выполняется без fish
командной строки WSL, все равно выполняется в оболочке по умолчанию.
Однако вам это и не нужно. Если команда не нуждается в оболочке, вы можете запустить ее напрямую, не проходя через оболочку (избегая накладных расходов) с помощью:
wsl -e ps -ef
PID TTY TIME CMD
1 ? 00:00:00 init
11 ? 00:00:00 init
12 ? 00:00:00 init
13 pts/0 00:00:00 ps
Вы заметите, что ни одна оболочка не запущена. Это вариант, который я рекомендовал выше ["wsl","-e","date"]
в Python.
Допустим, fish
это не ваша оболочка по умолчанию, и все же вы хотите, чтобы она работала.
wsl -e fish -c "ps -eH"
PID TTY TIME CMD
1 ? 00:00:00 init
20 ? 00:00:00 init
21 ? 00:00:00 init
22 pts/0 00:00:00 fish
29 pts/0 00:00:00 ps
Но не делайте wsl fish "ps -eH"
(или wsl fish -c date
). Это будет запускать рыбу внутри рыбы, что очень расточительно:
PID TTY TIME CMD
1 ? 00:00:00 init
11 ? 00:00:00 init
12 ? 00:00:00 init
13 pts/0 00:00:00 fish
20 pts/0 00:00:00 fish
22 pts/0 00:00:00 ps
Ответ №2:
С помощью вашей команды сначала subprocess.run()
запускается процесс, а затем ожидает его завершения. Как вы знаете, wsl fish
на самом деле это не заканчивается само по себе, что означает, что ваше приложение python теперь будет заблокировано на неопределенный срок.
Что вы на самом деле хотите сделать, так это запустить процесс, отправить ему данные через его STDIN и прочитать его вывод STDOUT.
Однако вы не можете сделать это так — например, вы не хотите блокировать интерпретатор!
proc = Popen(["wsl", "fish"], stdin=PIPE, stdout=PIPE, stderr=PIPE)
output, err = proc.communicate(b"date")
print(output)
communicate
также блоки. Если бы вы хотели, чтобы это продолжалось, вы бы сделали proc.stdin.write()
это, а затем proc.stdout.readline()
Ответ №3:
Первый подпроцесс.запуск запустит интерактивную раковину рыбы.
Только когда вы наберете exit, то date
запуститесь.