【发布时间】:2014-12-24 15:24:15
【问题描述】:
我正在尝试编写一个 python 脚本来编译并通过 Arduino 的命令行界面将相同的 hex 文件并行上传到多个微控制器。
我的脚本执行以下操作:
- 将 ino 文件编译为特定目录中的 hex 文件。例如,
- 将十六进制上传到所有 /dev/tty.usbXXXXXX。
这些是要求:
- 我必须能够并行上传到多个 /dev/tty.usb*。
- 我想打印所有子进程中的所有 stdout 和 stderr。以 DEVICE - STDOUT/STDERR - MSG 作为格式打开到我的主屏幕
- 我想将每个 Popen 中的 stdout 和 stderr 都保存到其自己的 tty.usb* 日志文件中。
现在我有:
import errno
import os
import re
import subprocess
ARDUINO_EXECUTABLE = '/Applications/Arduino.app/Contents/MacOS/JavaApplicationStub'
HEX_FOLDER_DIR = '/tmp/oyoroi'
LOG_FOLDER_DIR = './logs'
def get_devices():
"""Returns a list of tty.usbXXXXXX
Make sure you use the USB hub. This will force an extra character in the /dev/tty.usbXXXXXX
"""
ret = []
for device in os.listdir('/dev'):
if re.match('tty.usbmodem[0-9]{6}', device):
ret.append(device)
return ret
class Wrapper(object):
"""Wrapper for file objects
"""
def __init__(self, name, fobject):
self.name = name
self.fobject = fobject
def fileno(self):
return self.fobject.fileno()
def flush(self):
self.fobject.flush()
def write(self, a_str):
print self.name, a_str
self.fobject.write(a_str)
def main(fname):
"""Build once, but upload in parallel
"""
try:
os.makedirs(HEX_FOLDER_DIR)
except OSError as exc:
if exc.errno == errno.EEXIST and os.path.isdir(HEX_FOLDER_DIR):
pass
fname = os.path.abspath(fname)
# Builds the hex
command = "%s --verify --pref build.path=%s %s" % (ARDUINO_EXECUTABLE, HEX_FOLDER_DIR, fname)
print "(Build Command)", command
proc = subprocess.call(command, shell=True)
# Make the log directory
try:
os.makedirs(LOG_FOLDER_DIR)
except OSError as exc:
if exc.errno == errno.EEXIST and os.path.isdir(LOG_FOLDER_DIR):
# delete folder
import shutil
shutil.rmtree(LOG_FOLDER_DIR)
# and recreate again
os.makedirs(LOG_FOLDER_DIR)
# Upload in parallel
devices = get_devices()
processes = []
for device in devices:
device_path = '/dev/' + device
log_file_path = os.path.join(LOG_FOLDER_DIR, device + '.log')
with open(log_file_path, 'a') as logfile:
command = "%s --upload --pref build.path=%s --port %s %s" % \
(ARDUINO_EXECUTABLE, HEX_FOLDER_DIR, device_path, fname)
print "(Upload Command)", command
wstdout = Wrapper('%_STDOUT', logfile)
wstderr = Wrapper('%_STDERR', logfile)
proc = subprocess.Popen(command, shell=True, stdout=wstdout, stderr=wstderr)
processes.append(proc)
if __name__ == "__main__":
import sys
if len(sys.argv) != 2:
print "python upload.py <.ino>"
exit(1)
main(sys.argv[1])
我能够在每个日志文件中获得我想要的内容,但我的终端没有在屏幕上打印任何内容。它也在其他过程完成之前结束。
我错过了什么?
【问题讨论】:
-
stdout=wstdout不正确。subprocess.Popen()不接受类似文件的对象(在您的情况下,除了.fileno()之外的所有 Wrapper 方法都将被忽略,这就是您看不到任何内容的原因——没有打印任何内容(未调用print self.name, a_str))。它需要一个真实的文件(真实文件描述符)。见howteed_call()that uses multiple threads is implemented。这是how to do collect both stdout/stderr independently and print it to console in a single thread。
标签: python arduino pipe subprocess