如何响应标准输入,并同时打印到标准输出?

时间:2020-04-20 02:53:17

标签: python python-3.x linux bash python-multithreading

我有一个bash脚本,该脚本可以永远运行,并以不同的间隔打印一些信息。为简单起见;假设这是我的bash脚本;我们称之为mybashscript.sh

#!/bin/bash
while :
do
    echo "The loop has printed"
    sleep 5
done

这仅仅是出于简单的原因;我的实际脚本不是那么简单。 (我有大约30种非分支,非subshel​​l启动的bash脚本。)

我想编写一个将运行的python程序;

  • 运行此bash脚本
  • 从bash脚本的stdout获取输出;并对其进行解析(为简单起见;我们只想在每行的开头添加字符串[python])并打印出来。
  • 当python脚本终止时,将终止bash脚本。
  • 同时;响应python stdin中的行(为简单起见;假设我想在stdin上有键盘输入时跳过歌曲。

我有以下程序可以做到这一点;让我们称之为mywrapper.py(我在这里使用命令mpc next;因为如果被调用,这对我来说很容易实现;我戴着耳机)

#!/bin/env python
import os
import re
import sys
import threading
import subprocess

def response():
    """ Just one function to check if functions work """
    subprocess.call(['mpc', 'next'],
                    stdin=subprocess.DEVNULL,
                    stdout=subprocess.DEVNULL,
                    stderr=subprocess.DEVNULL)

def listen(inp):
    """ Respond to stdin """
    for line in inp:
        response()

if __name__ == '__main__':
    # Test the response function
    response()
    # Start the infinite loop
    SCRIPT = subprocess.Popen('/tmp/mybashscript.sh',
                              stdin=subprocess.DEVNULL,
                              stdout=subprocess.PIPE,
                              stderr=subprocess.DEVNULL)
    # Start the listener
    LISTEN = threading.Thread(target=listen,
                              args=(sys.stdin))
    LISTEN.start()
    # Respond to lines in the script
    while True:
        LINE = SCRIPT.stdout.readline()
        # If the script terminated; get out of loop to terminate program
        if not LINE:
           break

        print('[python]' + str(LINE))
        # Need this to stop buffering
        sys.stdout.flush()

但是; listen没有执行任何操作。响应功能工作正常;在第一次调用时。如何更改我的python脚本以响应输入?

也;需要两个键盘中断才能停止该程序。如何判断SIGTERM是否也会杀死所有子进程?

为避免XY问题;这正是我想要做的;

  • 我正在尝试编写一个将与另一个程序交互的程序。我在linux上;并且我想在使用i3 / sway时使用i3blocks在屏幕上显示信息。
  • 我想使用persist选项;仅当关联的脚本打印新行时,这将更改i3blocks显示的文本。
  • 我有一个名为music dash 脚本,它打印当前正在播放的歌曲的名称,并且仅在歌曲更改时才打印新行。这条路;如果我不播放任何歌曲,我不必轮询信息,也不必不断更新文本。
  • 我在其周围编写了一个名为sysinfo-i3bar的python包装器;基本上将字符串的输出格式化为json格式;因为我可以控制颜色和东西。 (我之所以不对破折号脚本进行完整的json解析,是因为我想重用原始脚本;但是在其他程序中,例如polybar;使用一个信息脚本,然后使用多个包装来处理多个场合因此很有帮助)到目前为止,一切都很好。
  • 如果我在i3blocks上单击屏幕上的块;取决于所单击按钮的字符(例如1表示左键单击或2表示右键单击)被发送到正在运行的脚本的stdin。我想做的就是对这些事件做出回应;例如,单击该区域时运行mpc toggle。我目前不知道该怎么做。
  • 我正在尝试对包装器中的stdin进行响应;而不是原始的破折号脚本,因为其他状态栏不能像这样工作。 (Polybar仅需要将其自身的语法包裹在文本上即可在点击时执行命令,如我的sysinfo-polybar包装器中所示。)

最终;我想打包这些脚本/包装并将其发布给社区。感谢您的帮助。

0 个答案:

没有答案
相关问题