线程循环在20分钟后崩溃(RPi/GPIO)

0 投票
3 回答
1019 浏览
提问于 2025-04-30 14:52

我在寻找帮助,希望能让这段代码更好地运行。这个程序在循环运行了一段时间后(大约15到20分钟)就会卡住。有一些用户告诉我,使用time.sleep()来进行同步不是个好主意,我在想这是不是我的问题。请在回复时用我的代码作为例子,因为我对Python还很陌生。越简单越好。

这段代码应该默认播放一个视频循环,当按下一个按钮(RPi/GPIO)时,会播放另一个视频。等这个视频播放完后,它会回到默认的循环视频。正如你所看到的,我在使用OMXPlayer。

#!/usr/bin/python

from time import sleep
import RPi.GPIO as GPIO
import subprocess
import time
import thread

GPIO.setmode (GPIO.BCM)
GPIO.setwarnings (False)

GPIO.setup(4, GPIO.IN)  # Button 1
GPIO.setup(9, GPIO.IN)  # Button 2
GPIO.setup(10, GPIO.IN) # Button 3
GPIO.setup(11, GPIO.IN) # Button 4
GPIO.setup(17, GPIO.IN) # Button 5
GPIO.setup(22, GPIO.IN) # Button 6
GPIO.setup(27, GPIO.IN) # Button 7

video_playing = False # Loop flag initial status

def welcome_loop():
    global playProcess
    while True:
        x = 1
        if not video_playing:
                print "Play Welcome Video"
                time.sleep(.05)
                playProcess=subprocess.Popen(['omxplayer','-b','Desktop/videos/loop/loop.mp4'],
                                                 stdin=subprocess.PIPE,stdout=subprocess.PIPE,
                                                 stderr=subprocess.PIPE,close_fds=True)
                time.sleep(24) # Length of video
        x += 1

def videos():
    #initialise a previous input variable to 0 (assume button not pressed last)
    prev_input = 0
    global video_playing
    while True:
        button1 = GPIO.input(27)
        if ((not prev_input) and button1):
                video_playing = True  # Set the flag (loop pauses)
                print "Stop Welcome Video"
                time.sleep(.5)
                playProcess.stdin.write('q') # Stop video      
                time.sleep(.5)
                print "Play Martin Lab - Reel"
                martinlab_reel=subprocess.Popen(['omxplayer','-b','Desktop/videos/martinlab_reel.mp4'],
                                                     stdin=subprocess.PIPE,stdout=subprocess.PIPE,
                                                     stderr=subprocess.PIPE,close_fds=True)
                time.sleep(30) # Length of video
                martinlab_reel.stdin.write('q')
                video_playing = False  # Unset the flag (loop continues)

        #update previous input
        prev_input = button1
        #slight pause to debounce
        time.sleep(.25)

        button2 = GPIO.input(9)
        if ((not prev_input) and button2):
                video_playing = True  # Set the flag (loop pauses)
                print "Stop Welcome Video"
                time.sleep(.5)
                playProcess.stdin.write('q') # Stop video
                time.sleep(.5)
                print "Play Shoppingcart"
                shoppingcart=subprocess.Popen(['omxplayer','-b','Desktop/videos/shoppingcart.mp4'],
                                                    stdin=subprocess.PIPE,stdout=subprocess.PIPE,
                                                    stderr=subprocess.PIPE,close_fds=True)
                time.sleep(111) # Length of video
                shoppingcart.stdin.write('q')
                video_playing = False  # Unset the flag (loop continues)

        #update previous input
        prev_input = button2
        #slight pause to debounce
        time.sleep(.25)

        button3 = GPIO.input(10)
        if ((not prev_input) and button3):
                video_playing = True  # Set the flag (loop pauses)
                print "Stop Welcome Video"
                time.sleep(.5)
                playProcess.stdin.write('q') # Stop video
                time.sleep(.5)
                print "Play Dodgeballs"
                dodgeballs=subprocess.Popen(['omxplayer','-b','Desktop/videos/dodgeballs.mp4'],
                                                    stdin=subprocess.PIPE,stdout=subprocess.PIPE,
                                                    stderr=subprocess.PIPE,close_fds=True)
                time.sleep(102) # Length of video
                dodgeballs.stdin.write('q')
                video_playing = False  # Unset the flag (loop continues)

        #update previous input
        prev_input = button3
        #slight pause to debounce
        time.sleep(.25)

        button4 = GPIO.input(11)
        if ((not prev_input) and button4):
                video_playing = True  # Set the flag (loop pauses)
                print "Stop Welcome Video"
                time.sleep(.5)
                playProcess.stdin.write('q') # Stop video
                time.sleep(.5)
                print "Play Hidden Camera"
                hiddencamera=subprocess.Popen(['omxplayer','-b','Desktop/videos/hiddencamera.mov'],
                                                    stdin=subprocess.PIPE,stdout=subprocess.PIPE,
                                                    stderr=subprocess.PIPE,close_fds=True)
                time.sleep(37) # Length of video
                hiddencamera.stdin.write('q') # Stop video
                video_playing = False  # Unset the flag (loop continues)

        #update previous input
        prev_input = button4
        #slight pause to debounce
        time.sleep(.25)

        button5 = GPIO.input(17)
        if ((not prev_input) and button5):
                video_playing = True  # Set the flag (loop pauses)
                print "Stop Welcome Video"
                time.sleep(.5)
                playProcess.stdin.write('q') # Stop video      
                time.sleep(.5)
                print "Play Light of Human Kindness"
                lohk_reel=subprocess.Popen(['omxplayer','-b','Desktop/videos/LOHK_short.mp4'],
                                                    stdin=subprocess.PIPE,stdout=subprocess.PIPE,
                                                    stderr=subprocess.PIPE,close_fds=True)
                time.sleep(83) # Length of video
                lohk_reel.stdin.write('q')
                video_playing = False  # Unset the flag (loop continues)

        #update previous input
        prev_input = button5
        #slight pause to debounce
        time.sleep(.25)

        button6 = GPIO.input(22)
        if ((not prev_input) and button6):
                video_playing = True  # Set the flag (loop pauses)
                print "Stop Welcome Video"
                time.sleep(.5)
                playProcess.stdin.write('q') # Stop video      
                time.sleep(.5)
                print "Play RVA Makerfest"
                rva_makerfest=subprocess.Popen(['omxplayer','-b','Desktop/videos/rva_makerfest.mp4'],
                                                    stdin=subprocess.PIPE,stdout=subprocess.PIPE,
                                                    stderr=subprocess.PIPE,close_fds=True)
                time.sleep(101) # Length of video
                rva_makerfest.stdin.write('q')
                video_playing = False  # Unset the flag (loop continues)

        #update previous input
        prev_input = button6
        #slight pause to debounce
        time.sleep(.25)

        button7 = GPIO.input(27)
        if ((not prev_input) and button7):
                video_playing = True  # Set the flag (loop pauses)
                print "Stop Welcome Video"
                time.sleep(.5)
                playProcess.stdin.write('q') # Stop video      
                time.sleep(.5)
                print "Play PartyBot - Reel"
                partybot_reel=subprocess.Popen(['omxplayer','-b','Desktop/videos/partybot_reel.mov'],
                                                    stdin=subprocess.PIPE,stdout=subprocess.PIPE,
                                                    stderr=subprocess.PIPE,close_fds=True)
                time.sleep(61) # Length of video
                partybot_reel.stdin.write('q')
                video_playing = False  # Unset the flag (loop continues)

        #update previous input
        prev_input = button7
        #slight pause to debounce
        time.sleep(.25)

thread.start_new_thread( videos, () ) # Videos thread
thread.start_new_thread( welcome_loop, () ) # Loop thread

while True:
    pass

GPIO.cleanup() #Reset GPIOs

错误信息(运行2小时后):

Unhandled exception in thread started by <function welcome_loop at 0xb6c8b3b0>
Traceback (most recent call last):
  File "./labmural2.py", line 32, in welcome_loop
    stderr=subprocess.PIPE,close_fds=True)
  File "/usr/lib/python2.7/subprocess.py", line 679, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1153, in _execute_child
    self.pid = os.fork()
OSError: [Errno 12] Cannot allocate memory

内存使用情况(HEAPY返回值):

Partition of a set of 26904 objects. Total size = 1957148 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
  0  12601  47   786404  40    786404  40 str
  1   6274  23   254548  13   1040952  53 tuple
  2   1756   7   126432   6   1167384  60 types.CodeType
  3     80   0   122944   6   1290328  66 dict of module
  4    203   1   108292   6   1398620  71 dict of type
  5   1709   6   102540   5   1501160  77 function
  6    121   0    98540   5   1599700  82 dict (no owner)
  7    203   1    90232   5   1689932  86 type
  8    121   0    70316   4   1760248  90 dict of class
  9   1054   4    42160   2   1802408  92 __builtin__.wrapper_descriptor

free -m:

             total       used       free     shared    buffers     cached
Mem:           247        159         87          0          7         75
-/+ buffers/cache:         76        170
Swap:           99          8         91
暂无标签

3 个回答

0

我遇到了一个问题,当我在Linux系统中查看打开的文件时,发现随着时间的推移,打开的文件数量在不断增加。所以当打开的文件数量达到“ulimit -n”这个限制时,脚本就停止了。我的解决办法是增加Linux中可以打开的文件数量,我通过下面的链接把这个数量增加到了1,000,000:

https://www.cyberciti.biz/faq/linux-increase-the-maximum-number-of-open-files/

但其实根本的解决办法是避免打开太多文件。(我只是用一个类来读取温度,但我不知道为什么打开的文件数量会随着时间增加)

0

使用线程和队列,而不是直接用线程和全局变量。

0

你可能是因为启动进程和等待它们完成的方式不对,导致内存或可用进程不够用。等你的程序运行了一段时间后,可以用 ps -AF 来查看当前正在运行的进程数量。

想象一下,你要播放的视频本来应该播放10秒,但实际上只播放了9秒。这会导致系统在第一个视频还没结束的时候,就试图重新开始播放。这是因为有 time.sleep() 的调用。最终,你会发现有很多视频播放器同时在运行同一个视频,这样就会耗尽内存或者超出操作系统允许的进程数量。

我建议把播放和等待的方式改成这样:

playProcess=subprocess.Popen(['omxplayer','-b','Desktop/videos/loop/loop.mp4'],
                                                 stdin=subprocess.PIPE,stdout=subprocess.PIPE,
                                                 stderr=subprocess.PIPE,close_fds=True)
playProcess.wait() # Wait for video to finish playing

撰写回答