从Python的subprocess中持续调用shell命令并解析输出。
从Python的subprocess中持续调用shell命令并解析输出。
我正在开发一个嵌入式应用程序,使用了来自CANBOAT存储库的一些预编译二进制文件。
有两个可用于使用的二进制文件:
actisense-serial
analyzer
在shell中,需要执行actisense -r /dev/ttyUSB0 | analyzer -json
命令来获取与USB端口连接的设备的信息。上述命令将JSON信息转储到STDOUT。
示例输出:
{"timestamp":"2018-08-30T16:27:23.629Z","prio":2,"src":3,"dst":255,"pgn":128259,"description":"Speed","fields":{"SID":106,"Speed Water Referenced Type":"Paddle wheel"}}
{"timestamp":"2018-08-30T16:27:23.629Z","prio":2,"src":6,"dst":255,"pgn":128259,"description":"Speed","fields":{"SID":106,"Speed Water Referenced Type":"Paddle wheel"}}
上述值将持续显示在STDOUT上。
我希望在Python脚本中使用上述shell命令来获取JSON值,解析它们并将它们保存到数据库中。
最初,我想使用subprocess.check_output
开始。
我尝试了以下代码:
import subprocess if __name_ == "__main__": while True: value = subprocess.check_output(['actisense-serial -r /ttyUSB0', '|', 'analyzer -json'], shell=True) print(value)
但是没有输出可用。我不确定如何将STDOUT的输出路由到check_output
。
我该如何实现,以便从shell命令中连续获取的JSON信息可以被解析并在应用程序中进一步使用?
问题的原因是原始代码使用了communicate()
方法来获取输出,这个方法会一次性获取所有输出内容,而不是连续地读取输出流。因此,代码需要修改为使用readline()
方法来连续读取输出流。
解决方法是使用Popen
的stdout
参数和stdin
参数来设置输出和输入的管道。通过将第一个进程的stdout
管道传递给第二个进程的stdin
管道,实现了连续地读取输出流。
下面是修改后的代码:
actisense_proc = subprocess.Popen(['actisense-serial', '-r', '/ttyUSB0'], stdout=subprocess.PIPE) analyzer_proc = subprocess.Popen(['analyzer', '-json'], stdin=actisense_proc.stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE) while analyzer_proc.poll() is None: print(analyzer_proc.stdout.readline())
注意,代码中没有使用shell=True
,而是使用了两个Popen
调用,并将第一个进程的输出流传递给第二个进程的输入流。