【问题标题】:Multiple writes to file多次写入文件
【发布时间】:2010-11-28 22:18:40
【问题描述】:

我有以下 python 代码,它期望来自串行端口的数据,并将其写入文件。

import time
import serial

def write_log ( text ):
    f = open('logger.log', 'a')
    f.write( text )
    f.close()

ser = serial.Serial()
ser.port = "/dev/ttyS0"
ser.baudrate = 4800
ser.open()
if ser.isOpen():
    while 1:
        while ser.inWaiting() <= 0:
            time.sleep(1)
            response = ser.read(ser.inWaiting())
            if len ( response ):
                write_log( response )
                print response

它在一定程度上起作用,因为一段时间后,它开始挂起,使 CPU 一直处于上升状态,并且不向 .log 文件写入任何内容(或有时只写入文本片段)。

这里的过程非常密集,因为我的串口每秒会写入一个 8 字节的字符串,然后这个 python 脚本应该会接收它,并将其内容写入日志文件。

我认为这里的问题是我打开和关闭文件的次数过多,这在某种程度上使整个过程变慢了。我不是 python wizz,所以任何关于改进此代码的帮助或建议将不胜感激。

提前致谢,

【问题讨论】:

  • 每秒 8 字节不是很密集; 8 MiB/s 可能很密集,但大多数 CPU 甚至可以应付。即使是运行在 4 MHz 的 Z80 也不会发现每秒 8 字节的密集型。
  • 我确实意识到这不是很密集,但不知何故,这段代码在一段时间后停止响应,并停止存储任何东西。我说密集,因为它会继续尝试将内容写入串行,即使 python 脚本没有将任何内容写入文本文件
  • 代码看起来是从串口设备读取,而不是写入。
  • "我有以下 python 代码,它期望来自串行端口的数据,并将其写入文件。"从串口读取并将其内容写入文件

标签: python io serial-port


【解决方案1】:

您的代码中有一个无限循环,当出现问题或串行设备不再打开时,您无法摆脱它。

可能使用:

while ser.isOpen():
    while ser.inWaiting() <= 0:
        time.sleep(1)
        response = ser.read(ser.inWaiting())
        if len(response):
            write_log(response)
            print response

甚至:

while ser.isOpen() && ser.inWaiting() <= 0:
    time.sleep(1)
    response = ser.read(ser.inWaiting())
    if len(response):
        write_log(response)
        print response

我也不确定睡眠;你最好只是在读取中等待数据可用。

当我想到它时,不知道串行类中可用的方法,我认为主循环应该尝试从串行设备读取,如果当前没有可用的内容,则愉快地挂起,并且仅在输入法表示没有更多输入 - 设备已关闭您,或以某种方式失败。

【讨论】:

  • 你的例子也会在一段时间后死掉
  • @Marcos:好的,但是如果没有串行包的规范(那是标准的 Python 吗?我对此表示怀疑),很难知道你需要做什么。加倍如此,因为我只能真正阅读 Python 而不能流利地编写它。但是您应该以同步读取循环(单数 - 非嵌套)为目标;它只是挂在读取中,直到准备好数据。如果该功能尚不可用,那么您可能需要编写一个功能来提供它。如果您确实需要轮询,您可能希望使用微睡眠功能更频繁地进行轮询,而不是每秒一次。
【解决方案2】:

我认为这里的问题是您正在轮询更新。

Python 的serial.read() 函数实际上会阻塞当前线程,直到线程上的某些内容变得可读,直到超时。因此,您应该做的是打破另一个线程来处理串行 IO。让它无限循环,检查一个条件(主线程希望你保持监听并且串行端口仍然可用)。该线程将执行以下操作:

while ser.isOpen() && thisthread_should_keep_doing_this:
    response = ser.read(ser.inWaiting())
    if len(response):
        write_log(response)
        print response

然后,当您希望它退出时,您的主线程设置thisthread_should_keep_doing_this=False,当您的从线程完成读取时,它会自行终止。

两件事:

  • 读取超时确实比较频繁。
  • 不要“远程杀死”线程。给它一个消息,让它自己杀死。远程杀死线程会造成可怕的混乱。

http://pyserial.sourceforge.net/examples.html#miniterm

【讨论】:

  • 不确定我是否真的了解这里要做什么。同样,我不是 python wizz,也从未使用过其中的线程。但是,您的想法似乎是解决我的问题的明智之选
  • @Marcos 这个想法很简单,但如果有意义的话,真的很难理解。基本上,阻塞 IO 就像睡眠一样。您的线程将在两种情况下唤醒:数据出来或延迟到期。然后您要做的是检查端口是否打开并且您不想退出,然后尝试再次读取并让读取阻塞。通过创建两个线程,您可以牺牲一个用于此目的,一个用于处理程序的主要业务(即使只是等待“退出”指令)。
  • 像这样阻塞 IO,如果有大量数据进来,你会立即读取。如果没有,您将在超时间隔内休眠。使用您的解决方案,您可以睡 1 秒钟,然后拉动那里的任何东西。因此,在那 1 秒内,您可能正在使用时钟周期来读取数据,但实际上并非如此。然后是大量数据......你会得到不可预测的结果。
  • 我也从未在 Python 中做过线程。我在 Windows 上使用串行 IO 进行了 C,而这样做的方法是阻塞 IO。
猜你喜欢
  • 1970-01-01
  • 2015-01-14
  • 1970-01-01
  • 2020-05-24
  • 1970-01-01
  • 1970-01-01
  • 2013-03-08
  • 2013-09-23
  • 2017-03-26
相关资源
最近更新 更多