Как ответить на стандартный ввод при запуске другой функции? - PullRequest
0 голосов
/ 04 апреля 2019

Я пытаюсь написать скрипт на 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 #" && 
            get_text
    done
}

get_action () {
    case $1 in
        1)  # Left
            /usr/bin/pactl set-sink-mute @DEFAULT_SINK@ toggle > /dev/null 2>&1 ;;
        2) # Middle
            ;;
        3) # Right
            [ -x '/usr/bin/pavucontrol' ] && /usr/bin/pavucontrol > /dev/null 2>&1 & disown ;;
        4) # Scroll Up
            if [ "$_volm" -ge 100 ] ; then
                /usr/bin/pactl set-sink-volume @DEFAULT_SINK@ 100%  > /dev/null 2>&1
            else
                /usr/bin/pactl set-sink-volume @DEFAULT_SINK@ +5% > /dev/null 2>&1
            fi ;;
        5) # Scroll Down
            /usr/bin/pactl set-sink-volume @DEFAULT_SINK@ -5%  > /dev/null 2>&1 ;;
    esac
}

get_loop & 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)

Функции работают по отдельности, но как мне заставить их работать одновременно?Я думал о том, чтобы сделать один цикл, и ждать, пока событие или что-то есть на stdin;но могу ли я это сделать?

(Подробнее о задаче, которую я пытаюсь выполнить, я пытаюсь записать блоклет для pulseaudio в i3blocks . Скрипт выводит строку JSONотформатированный текст, который читается процессом, и информация выводится в моей строке состояния. Каждый раз, когда что-то меняется с pulseaudio, мой скрипт печатает обновленную строку. i3blocks также отправляет строку в формате JSON, которая является информацией, когда происходит событие щелчка мыши,для которого я решил отключить звук, увеличить / уменьшить громкость или запустить программу. У меня есть она, работающая с bash, но я также изучаю python, и преобразование моих сценариев bash в python - это игрушечный проект, в который я должен вникнуть.)

Ответы [ 2 ]

0 голосов
/ 02 мая 2019

& в последней строке скрипта 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 с &. Или asyncio модуль и ключевые слова Python async / await.

0 голосов
/ 04 апреля 2019

Ваш bash-файл никогда не принимает никаких входных данных и не дозирует python-файл, поскольку у вас бесконечный цикл и вы никогда не вызываете функцию response.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...