#python #stdin
#python #stdin
Вопрос:
Я пытаюсь написать скрипт на python, который будет выводить текст в цикле и отвечать на stdin, если в нем что-то печатается. (Я планирую использовать этот скрипт python для взаимодействия с другой программой)
Ранее я написал скрипт для этого в bash и теперь хочу узнать, как это сделать с помощью python. Раньше я делал это в bash с помощью следующего скрипта;
#!/bin/sh
get_text () {
echo "Some stuff here"
}
get_loop() {
get_text
/usr/bin/pactl subscribe | while read -r line ; do
echo $line |
grep -q -e "sink" -e "'change' on server #" amp;amp;
get_text
done
}
get_action () {
case $1 in
1) # Left
/usr/bin/pactl set-sink-mute @DEFAULT_SINK@ toggle > /dev/null 2>amp;1 ;;
2) # Middle
;;
3) # Right
[ -x '/usr/bin/pavucontrol' ] amp;amp; /usr/bin/pavucontrol > /dev/null 2>amp;1 amp; disown ;;
4) # Scroll Up
if [ "$_volm" -ge 100 ] ; then
/usr/bin/pactl set-sink-volume @DEFAULT_SINK@ 100% > /dev/null 2>amp;1
else
/usr/bin/pactl set-sink-volume @DEFAULT_SINK@ 5% > /dev/null 2>amp;1
fi ;;
5) # Scroll Down
/usr/bin/pactl set-sink-volume @DEFAULT_SINK@ -5% > /dev/null 2>amp;1 ;;
esac
}
get_loop amp; while read button ; do get_action $button ; done
Который работает так, как я предполагал, что это сработает. До сих пор в python у меня есть это;
#!/usr/bin/python
import sys
import time
def respond(x=0):
while True:
x = int(sys.stdin.readline())
print(x)
def loop(t=1):
x = 0
while True:
x = 1
print('Delay is ' str(t) ' and looped ' str(x) ' times.')
time.sleep(t)
loop(1)
respond(0)
Функции работают по отдельности, но как мне заставить их работать одновременно? Я думал о создании одного цикла whil и ожидании события или чего-то в stdin; но могу ли я это сделать?
(Для получения подробной информации о задаче, которую я пытаюсь выполнить, я пытаюсь написать блоклет для pulseaudio в i3blocks. Скрипт выводит строку текста в формате JSON, который считывается процессом, и информация печатается в моей строке состояния. Каждый раз, когда что-то меняется с помощью pulseaudio, мой скрипт печатает обновленную строку. i3blocks также отправляет строку в формате JSON, которая является информацией, когда происходит событие щелчка мыши, для которого я решаю отключить звук, увеличить / уменьшить громкость или запустить программу. У меня есть это работает с bash, но я также изучаю python и преобразование моих сценариев bash в python — это игрушечный проект, в котором я должен вникать в эти вещи.)
Комментарии:
1. Если вы хотите запустить две функции одновременно, вы можете использовать потоки.
2. Многопоточность или многопроцессорность. В противном случае GIL не позволит вам этого сделать.
3. Это то, чего я боялся. Есть ли способ выполнить продолжение в бесконечном цикле для какого-либо события или чего-либо в stdin?
Ответ №1:
Ваш файл bash никогда не принимает никаких входных данных и не дозирует файл python, поскольку у вас бесконечный цикл и вы фактически никогда не вызываете функцию ответа.
Комментарии:
1. Я упростил свою функцию bash в качестве демонстрации; я обновлю ее оригинальной.
Ответ №2:
amp;
В последней строке сценария Bash запускается get_loop
асинхронно. Одним из способов достижения этого в Python является threading
модуль:
#!/usr/bin/env python3
import sys
import time
from itertools import count
from threading import Thread
def respond():
total_sum = 0
while True:
total_sum = int(sys.stdin.readline())
print(total_sum)
def loop(delay):
for i in count():
print(f'Delay is {delay} and looped {i} times.')
time.sleep(delay)
def main():
thread = Thread(target=loop, args=[1])
thread.daemon = True
thread.start()
respond()
if __name__ == '__main__':
main()
Другими способами было бы использование multiprocessing
модуля, который можно использовать для запуска одной из функций в другом процессе, что на самом деле делает Bash amp;
. Или asyncio
модуль и ключевые слова Python async
/ await
.