Python 在Raspberry pi上作为服务运行时,脚本使用了太多的cpu电源

Python 在Raspberry pi上作为服务运行时,脚本使用了太多的cpu电源,python,raspberry-pi3,systemd,Python,Raspberry Pi3,Systemd,我在raspberry pi上运行了这个代码片段。它基本上拍摄人们进出我房间的照片 import RPi.GPIO as GP import os import socket def opencallback(channel): print(GP.input(channel)) if GP.input(channel): global closeEvent closeEvent = 1 else: global ope

我在raspberry pi上运行了这个代码片段。它基本上拍摄人们进出我房间的照片

import RPi.GPIO as GP
import os
import socket


def opencallback(channel):
    print(GP.input(channel))
    if GP.input(channel):

        global closeEvent
        closeEvent = 1
    else:
        global openEvent
        openEvent = 1


def transmit(message):
    s = socket.create_connection((host, port))
    s.send(message)
    s.close()


def capture(cam, gpiolist, quick):
    GP.output(cam1, gpiolist[0])
    GP.output(cam2, gpiolist[1])
    GP.output(cam3, gpiolist[2])

    if quick:
        cmd = "raspistill -o capture_%d.jpg -t 2" % cam
    else:
        cmd = "raspistill -o capture_%d.jpg" % cam
    os.system(cmd)


# init
GP.setwarnings(False)
GP.setmode(GP.BOARD)

cam1 = 7
cam2 = 11
cam3 = 12
doorIn = 40
ledOut = 38

GP.setup(cam1, GP.OUT)  # camera Mux1
GP.setup(cam2, GP.OUT)  # camera Mux2
GP.setup(cam3, GP.OUT)  # camera Mux3
GP.setup(ledOut, GP.OUT)  # LED OUT GPIO 20
GP.setup(doorIn, GP.IN)  # Door detector in GPIO 21

GP.add_event_detect(doorIn, GP.BOTH, callback=opencallback)

GP.output(ledOut, False)
openEvent = 0
closeEvent = 0
host = '192.168.1.111'
port = 13579

# main
while True:
    if openEvent == 1:
        transmit("2-01")
        capture(2, (False, True, False), True)  # front cam
        transmit("2-03")
        openEvent = 0
    else:
        pass

    if closeEvent == 1:
        transmit("2-02")
        GP.output(ledOut, True)
        capture(3, (False, False, True), False)
        GP.output(ledOut, False)
        transmit("2-04")
        closeEvent = 0
    else:
        pass
通常,我只是通过命令行使用标准调用来运行它,它不会加载系统

但是,我最近使用systemd/systemctl将其转换为服务,因为我想在启动pi时在后台加载该脚本。现在,这个脚本自己吞噬了整个处理器核心(正如htop所报告的)。在转换过程中,我没有对代码本身做任何更改,当我以旧的方式运行它时,它仍然可以正常工作。大多数时候,它只是简单地运行while循环,不做任何事情,等待GPIO的回调,然后执行一些函数并返回while传递行为


我的问题是:是什么导致了这两种执行方法在计算功耗上的差异?是否有办法解决此问题?

边缘检测/回调代码非常有效,仅在事件发生时调用。但是,顶层
while True:
循环效率极低

考虑以下修改:

try:
    import Queue as queue # Python 2.x
except ImportError:
    import queue          # Python 3.x

eventQueue = queue.Queue()

def opencallback(channel):
    eventQueue.put(GP.input(channel))

# ...your existing setup code here, specifically including:
GP.add_event_detect(doorIn, GP.BOTH, callback=opencallback)

while True:
    event = eventQueue.get()
    if event:
        transmit("2-01")
        capture(2, (False, True, False), True)  # front cam
        transmit("2-03")
    else:
        transmit("2-02")
        GP.output(ledOut, True)
        capture(3, (False, False, True), False)
        GP.output(ledOut, False)
        transmit("2-04")

请注意,这与systemd无关——任何其他调用方法都会遇到同样的CPU使用问题。

为什么不让回调直接触发打开和关闭事件的操作?让循环运行一小段时间。睡眠

def opencallback(channel):
    print(GP.input(channel))
    if GP.input(channel):
        transmit("2-02")
        GP.output(ledOut, True)
        capture(3, (False, False, True), False)
        GP.output(ledOut, False)
        transmit("2-04")
        closeEvent = 0
    else:
        transmit("2-01")
        capture(2, (False, True, False), True)  # front cam
        transmit("2-03")

您是否可以使用
nice
?尝试使用。这将暂停线程,让你的CPU做其他事情(包括什么都不做),我可以包括time.sleep和我可能会错过任何事件,但这并不能解释所需计算能力的主要差异。我也不知道什么是好的。@Slylandro,我不知道这将如何提高CPU效率,无论你如何运行它。处于一个进行连续轮询的紧密循环中总是一项昂贵的操作。我几乎想知道,您在命令行中测试的版本是否像登录到控制台一样(通过关联,导致进程阻塞,直到可以写入输出)有效地执行了延迟。Linux内核能够为某些进程授予优先级。这被称为过程的“精确性”。可以设置systemd资源的精确性,并且它作为systemd资源运行时的精确性可能与作为cli应用程序运行时的精确性不同。哦,我真的很喜欢!我完全忘记了Python有一个现成的队列库。然而,这是否给了CPU一个切换时间的机会?sleep有吗?@Ketzak,是的,它有。我写的所有其他脚本都没有这个问题,因为它们实际上轮询套接字连接的方式与此类似。今晚我花了时间正确地实现了它,是的,它解决了问题。再次感谢!简短回答:因为这样你就可以提示整个过程,并且不会在回调中停留太长时间(拍摄照片需要几秒钟,我可能会错过第二次回调)啊,这是有道理的。