为了从逻辑控制器捕获数据,我使用screen作为终端仿真器,并通过KeySpan USA-19HS USB Serial Adapter连接我的MacBook。我创建了下面的bash脚本,这样我就可以键入talk2controller <filename>
,其中filename是数据文件的名称。在
#!/bin/bash
if [ -z "$1" ]; then
echo Please provide the filename to save the logfile
exit
fi
LOGFILE=$1
echo "logfile $1" > screenrc # Set the logfile filename
echo "logfile flush 1" >> screenrc # Wait 1 sec before flushing buffer to filesystem
screen -L -c screenrc /dev/tty.KeySerial1 19200
我已经更改了日志文件的文件名,并从默认的10秒改为1秒,以便在将日志文件缓冲区刷新到文件系统之前等待。我将这些命令保存到screenrc
。然后我给屏幕打电话:
-L
-启用日志记录-c screenrc
-覆盖默认配置文件/dev/tty.KeySerial1 19200
-使用19200波特率与串行端口通信我记录的每个测试大约需要3-6分钟,并且包含速度、加速度和位置信息。根据加速度,我知道这个测试是有效的。目前,我在等待测试之后运行Python matplotlib脚本来绘制速度、加速度和位置,以便在进行下一个测试之前查看测试是否有效。在
为了节省时间,我宁愿在测试进行到一半时绘制数据,而数据仍在捕获中。在
在我看来,有两种方法可以在捕获更多数据时绘制数据:
问题3:有没有更好的选择我没有想到?在
我认为选择2是最好的选择。当您接收到输入的每个字节时,您可以完全控制对其执行的操作。您可以有一个非常简单的Python脚本,它在读取数据时将数据写入磁盘。绘图代码可以在一个完全独立的进程中运行,该进程由
fork()
创建。要从一个进程到另一个进程获取数据,可以(a)让第一个进程也写入socketpair()
或其他IPC机制;或者(b)将output file对象配置为行缓冲,使其在写入每一整行之后显式同步,并在第二个进程中监视它是否有新内容。在选项1的问题是您无法控制
screen
的缓冲行为。您可以监视其日志文件中的新内容,但日志代码需要准备好,以便同时处理不完整的行和大数据块。根据具体的缓冲行为,在screen
进程退出之前,您可能根本看不到任何数据!在我认为选项1是完全可行的,因为您可以轻松地在只读管道中使用Python“tail”日志文件,这样当
screen
仍在写入日志文件时,不会对其造成损害。在跟踪文件时,您可以在日志文件中检测到新的日志事件时执行指定的操作。在如果您很好奇,并且希望看到一些工作代码,我的一个个人项目利用了这个功能。这个项目叫做thrasher-logdrop,核心是{a2}。基本流程是:
do_tail()
跟踪文件tail_lines()
监视日志事件handle_line()
对事件执行操作选项1和2都可以,但是哦,天哪,为了一切都好,避免为此使用线程!你最终会得到两个世界中最糟糕的结果:锁定问题,和绘图线程中的异常无论如何都会杀死整个程序(包括日志线程)。正如其他人所提到的,使用两个单独的过程是可以的。
screen
是一种奇怪的工具选择,就像用python手工编写代码一样。我只是将talk2controller脚本重写为这个简单的脚本:(如果希望脚本的每次运行都附加到文件中,而不是从头重写,也可以使用
>>logfile
。)另一个问题是,只要有人在写,程序是否可以从文件中读取。这个问题的一个更具体的版本是:如果一行日志在您试图阅读时被写了一半呢?在
答案是:你可以这样做,但你是对的,你不能保证一行字在你读的时候不会写一半。(如果您为
cat
或screen
编写自己的替代品,您实际上可以通过始终使用os.read()
而不是sys.stdout.write()
或print
写入文件来实现这一保证。)然而,无论如何也不需要这种保证。你只需要在阅读文件时小心,你永远不会有问题。本质上,不完整的行就是不以
^{pr2}$\n
换行符结尾的行。因此:由于
\n
字符是日志中每一行写入的最后一个字符,因此您肯定知道,如果您读取\n
字符,那么在它正确写入之前的所有内容都是正确的。在相关问题 更多 >
编程相关推荐