防止subprocess.call()显示文本

0 投票
1 回答
596 浏览
提问于 2025-04-18 08:07

我在使用树莓派(raspbian)时,修改了一个幻灯片脚本,这个脚本是用Python写的,能读取一个PIR运动传感器。

在原来的脚本中,PIR传感器在一段时间内没有检测到运动后,会关闭显示器(HDMI),然后再打开。我想让运动传感器在检测到运动时显示一张新图片。

所以,每当PIR传感器被触发时,我就会调用这个函数:

def new_pic():
    sys.stderr.write("\x1b[2J\x1b[H")
    myList = []
    file = open("dir.txt","rt")
    for line in file:
        myList.append(line)
    file.close()
    count = len(myList)
    rnd = randint(0,count-1)
    current_image = myList[rnd]
    current_image = current_image[:-1]
    proc = subprocess.Popen(["pgrep", "fbi"], stdout=subprocess.PIPE)
    for pid in proc.stdout:
        os.kill(int(pid), signal.SIGTERM)
    subprocess.call(["fbi", "-noverbose", "-a", "-T", "2", "/home/pi/photoframe/photos/"+current_image])

我在定时任务(crontab)中使用rsync来保持图片库的更新。每次rsync后,我会把文件列表写入' dir.txt'。

这个方法是有效的,唯一的问题是每次加载新图片时,终端的文本会闪现一下。我尝试通过修改-bashrc把提示符改成黑色,并在运行我的Python脚本前执行'clear'命令来解决这个问题。

我现在遇到的问题是:

当调用fbi时,它会显示

using "DejaVu Sans Mono-16", pixelsize=16.67 file=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono.ttf

我试着在fbi命令的末尾添加

> /dev/null

但它并没有理会。

在之前的尝试中,我不断地调用新的fbi实例,但它们会在顶部堆积,最终导致树莓派资源耗尽。另一种方法是跟踪fbi的实例,并在调用下一个实例后结束它们……

我已经在这个问题上绕了好几周了,任何帮助都会非常感激。

后续更新:

第一个回答确实去掉了fbi的输出(subprocess.call)。

现在我看到了一些东西……它闪过得很快——白色的文字在闪烁。

我觉得这和这个if语句有关:

if io.input(PIR_PIN):
    if time.time() > (last_flip + SWITCH_TIMER):
         new_pic()

每次PIR被触发并且经过足够的时间后,它会被调用8到10次……

我原以为这个时间判断只会让new_pic()被调用一次。last_flip在fbi显示新图片后被设置为当前时间……

我该如何确保new_pic()只被调用一次呢?

谢谢!

安德鲁

1 个回答

2

根据关于 subprocess 的文档,subprocess 是用来启动另一个程序的,它有一些参数,比如 stdin、stdout 和 stderr,这些参数可以让你把程序的输入输出重定向到其他文件。

默认情况下,这些参数是 None,这意味着新启动的程序会继承父程序的输入输出文件,这就是为什么它会把文本泄露到你漂亮的界面里的原因。

你可以打开一个文件,甚至可以使用 /dev/null 作为一个黑洞,把输出发送到那里,方法如下:

shutup = open("/dev/null","w") 
subprocess.call(["fbi", "-noverbose", "-a", "-T", "2", "/home/pi/photoframe/photos/"+current_image], 
                stdout=shutup,
                stderr=shutup)

另一方面,你可能想要保存输出,并在 Python 中解析它,以确保 fbi 按照预期执行了操作。

撰写回答