Как реагировать на stdin при запуске другой функции?

#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 .