在屏幕中记录数据时读取Python中的文件

2024-10-01 07:51:23 发布

您现在位置:Python中文网/ 问答频道 /正文

背景

为了从逻辑控制器捕获数据,我使用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。然后我给屏幕打电话:

  1. -L-启用日志记录
  2. -c screenrc-覆盖默认配置文件
  3. /dev/tty.KeySerial1 19200-使用19200波特率与串行端口通信

我记录的每个测试大约需要3-6分钟,并且包含速度、加速度和位置信息。根据加速度,我知道这个测试是有效的。目前,我在等待测试之后运行Python matplotlib脚本来绘制速度、加速度和位置,以便在进行下一个测试之前查看测试是否有效。在

为了节省时间,我宁愿在测试进行到一半时绘制数据,而数据仍在捕获中。在

问题

在我看来,有两种方法可以在捕获更多数据时绘制数据:

  • 选项1:使用屏幕记录数据,并让Python matplotlib脚本读取部分日志文件。
    • 问题1:如果Python脚本读取日志文件,而screen仍在向日志文件中写入数据,会有什么问题?在
  • 选项2:从使用屏幕切换到使用pySerial。然而,在测试期间绘制数据要比简单地在测试期间捕获数据的优先级低。我不能承受代码绘图部分的异常导致数据记录失败。这就是屏幕的优点,它只是转储数据,而不尝试做任何其他事情。
    • 问题2:如果我要切换到pySerial,我可以运行两个线程来减少代码的绘图部分不影响数据捕获代码的可能性吗?这对我有什么好处吗?在

问题3:有没有更好的选择我没有想到?在


Tags: 文件the数据代码echo脚本bash屏幕
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脚本重写为这个简单的脚本:

stty -F /dev/tty.KeySerial1 19200 raw
cat </dev/tty.KeySerial1 >logfile

(如果希望脚本的每次运行都附加到文件中,而不是从头重写,也可以使用>>logfile。)

另一个问题是,只要有人在写,程序是否可以从文件中读取。这个问题的一个更具体的版本是:如果一行日志在您试图阅读时被写了一半呢?在

答案是:你可以这样做,但你是对的,你不能保证一行字在你读的时候不会写一半。(如果您为catscreen编写自己的替代品,您实际上可以通过始终使用os.read()而不是sys.stdout.write()print写入文件来实现这一保证。)

然而,无论如何也不需要这种保证。你只需要在阅读文件时小心,你永远不会有问题。本质上,不完整的行就是不以\n换行符结尾的行。因此:

^{pr2}$

由于\n字符是日志中每一行写入的最后一个字符,因此您肯定知道,如果您读取\n字符,那么在它正确写入之前的所有内容都是正确的。在

相关问题 更多 >