在Python中同步Linux系统命令和while循环

时间:2014-12-26 00:06:51

标签: python linux multithreading raspberry-pi

使用RaspberryPi系统,我必须将Raspbian系统命令(raspivid -t 20000)与从传感器连续读取的while循环同步,并将数据存储在数组中。 Raspbian命令通过RaspberryPi摄像机CSI模块启动视频录制,我必须确保它在传感器采集的同一时刻开始。我看到很多解决方案让我在multiprocessingthreadingsubprocess,ecc等模块中感到困惑。到目前为止,我唯一理解的是os.system()函数阻止执行以下python命令,只要它运行就放在脚本中。所以,如果我尝试:

import os
import numpy as np

os.system("raspivid -t 20000 /home/pi/test.h264")
data = np.zeros(20000, dtype="float") #memory pre-allocation supposing I have to save 20000 samples from the sensor (1 for each millisecond of the video)
indx=0
while True:
    sens = readbysensor() #where the readbysensor() function is defined before in the script and reads a sample from the sensor
    data[indx]=sens
    if indx==19999:
         break
    else:
         indx+=1

while-loop仅在os.system()函数完成时运行。但正如我上面所写,我需要两个进程同步并且并行工作。有什么建议吗?

2 个答案:

答案 0 :(得分:2)

最后添加一个&,以使进程分离到后台:

os.system("raspivid -t 20000 /home/pi/test.h264 &")

根据bash手册页:

  

如果命令由控制操作员&,shell终止   在子shell中在后台执行命令。外壳确实如此   不要等待命令完成,返回状态为0。

此外,如果您希望最小化循环在执行raspivid后开始所需的时间,则应在呼叫前分配dataindx

data = np.zeros(20000, dtype="float")
indx=0
os.system("raspivid -t 20000 /home/pi/test.h264 &")
while True:
    # ....

<强>更新
由于我们在评论中进一步讨论过,很明显没有必要像raspivid那样“同时”启动循环(无论这意味着什么),因为如果你试图从中读取数据I2C并确保您不会遗漏任何数据,您最好在运行raspivid之前开始读取操作。通过这种方式,您可以确定在此期间(无论这两次执行之间存在多大延迟),您都不会错过任何数据。
考虑到这一点,您的代码可能如下所示:

data = np.zeros(20000, dtype="float")
indx=0
os.system("(sleep 1; raspivid -t 20000 /home/pi/test.h264) &")
while True:
    # ....

这是我们在运行raspivid之前添加1秒延迟的最简单版本,因此我们有时间进入while循环并开始等待I2C数据。
这有效,但它不是生产质量代码。为了获得更好的解决方案,请在一个线程中运行数据采集功能,在第二个线程中运行raspivid,保留启动顺序(首先启动读取线程)。
像这样:

import Queue
import threading
import os

# we will store all data in a Queue so we can process
# it at a custom speed, without blocking the reading
q = Queue.Queue()

# thread for getting the data from the sensor
# it puts the data in a Queue for processing
def get_data(q):
    for cnt in xrange(20000):
        # assuming readbysensor() is a
        # blocking function
        sens = readbysensor()
        q.put(sens)

# thread for processing the results
def process_data(q):
    for cnt in xrange(20000):
        data = q.get()
        # do something with data here
        q.task_done()

t_get = threading.Thread(target=get_data, args=(q,))
t_process = threading.Thread(target=process_data, args=(q,))
t_get.start()
t_process.start()

# when everything is set and ready, run the raspivid
os.system("raspivid -t 20000 /home/pi/test.h264 &")

# wait for the threads to finish
t_get.join()
t_process.join()

# at this point all processing is completed
print "We are all done!"

答案 1 :(得分:2)

您可以将代码重写为:

import subprocess
import numpy as np

n = 20000
p = subprocess.Popen(["raspivid", "-t", str(n), "/home/pi/test.h264"])
data = np.fromiter(iter(readbysensor, None), dtype=float, count=n)

subprocess.Popen()在不等待raspivid结束的情况下立即返回。