Python字节字符串数据流

时间:2017-12-06 12:40:07

标签: python

我在Raspberry Pi 3上使用Python(3)。我的应用程序是数据采集和日志记录。我的问题与正确拆分和解释作为字节串接收的串行数据有关:

在我的应用程序中,以下列一般形式接收通过两个或多个非查询(USB)串行端口在输入缓冲区中连续累积和读取的原始数据。该字符串往往更长,但以下内容应足以作为示例:

  

B '+ 00000 \ r \正00210 \ r \ N + 00360 \ r \ N + 00300 \ r \正00163 \ r \ N + 00399 \ r \ N' < / p>

我正在使用 serial.read(serial.in_waiting)来接收数据。我发现这是最好的方法,因为我的独立数据源是异步的,不断吐出它们的值(大约每秒50个样本)并且数据广播速率略有不同(只是足以令人讨厌)。

我发现由于某些原因,我无法可靠地使用“readline()”来简化我的任务,包括 - 如果您对此有任何见解,请对此进行评论 - 事实上,无论出于何种原因,在“readline()”之后,我的系统上的“in_waiting”值不会重置为零。

不幸的是,“in_waiting”方法通常会生成数据,而不是如上所示那样整齐地终止。可能的变体,表示在给定的读取尝试中可能通过串行端口进行的操作包括:

  

B'+ 00000 \ r \正00210 \ r \ N + 00360 \ r \ N + 00300 \ r \正00163 \ r \ N + 003

  

B '+ 00000 \ r \正00210 \ r \ N + 00360 \ r \ N + 00300 \ r \正00163 \ R'

  

B '+ 00000 \ r \正00210 \ r \ N + 00360 \ r \ N + 00300 \ r \正00163'

  

B '+ 00000 \ r \正00210 \ r \ N + 00360 \ r \ N + 00300 \ r \ N - '

也就是说,读取时并非所有终端数据都是完整的。

我一直在尝试使用“decode”和“split”以及“list”和“map”函数来解释所有可用的完整数据(那些用\ r \ n正确终止的数据) n)为了让我可以动态地使用数值进行额外的工作。一直以来,我的目的是保留在读取结束时可能已收到的任何部分数据,以便在下一个读取周期中附加它们。

我的尝试并没有成功解决上述所有情况,这就是为什么我对那些比我更熟悉Python编程语言的成员更有吸引力。

请考虑评论一下(在Python中)最有效的方式:

1。从上面显示的数据中获取整数值列表。

2. :如果转换未正确终止,则从转换中排除不完整的尾随数据。

3. 保留所有未完成的跟踪数据,以便在后续阅读时附加。

如果你过去曾经处理过像我这样的情况,我希望能够从你的经验中学习,我将继续自己探讨这个问题。

2 个答案:

答案 0 :(得分:0)

[这不是答案,但评论时间太长了]

把我所说的一切都拿出来,我不是专家,我只是在抛出一些想法!

所有完整的值是否都是相同的长度?在这种情况下,您可以将它全部转储到io.BytesIO个流(https://docs.python.org/3/library/io.html#binary-i-o)并获取下一个n个字节(其中n = len(complete_value))?

您说您尝试使用decodesplitlistmap解决此问题。你能解释一下你到底做了什么吗?因为我没有看到类似的东西出了什么问题:

incomplete_value = b''
my_ints = []
while <there_is_data>:
    tmp = incomplete_value + get_my_data() # get a new batch of data and append it
    tmp_split = tmp.split(b'\r\n') # split the data on newlines
    complete_data = tmp_split[:-1] # get all but the last item
    incomplete_value = tmp_split[-1] # save the last item
    my_ints += [int.from_bytes(x) for x in complete_data] # creates a list of ints

答案 1 :(得分:0)

我将在前面加上#34;回答&#34;对于我自己的问题有两件事:(1)我并非100%确定它是我认为适当的礼仪。如果没有,我问其他人&#39;赦免。而(2),我将发布的解决方案仍然是形成性的。也就是说,它有效,但我真的想要掌握一种比我自己更好,更简洁和/或更有效的方法。

那就是说,这就是我所做的,删除了关键词的细节,只是一点背景:

为了这个小主题的访问者的利益,我正在从具有相同长度的块中的多个串行设备( 9600,8N1 - 不重要)中读取数据 - 至少当它们是完成,正确终止。 OP包含格式的代表性样本。

要阅读和存储数据,我目前正在使用:

#ACQUIRE MOST-RECENT DATA
MRD1 = ser1.read(ser1.in_waiting)

#LOG RAW DATA IMMDEDIATELY
fil1.write(MRD1)

而且,回想一下,最初我曾假设读完全线&#34;线&#34;而不是字符串字符串将是首选方法,以避免拆分条目,所有开销,等等。但不。有各种各样的事情可以说明这种天真的假设。其中之一是&#34; readline()&#34;没有清除&#34; in_waiting&#34;算我的情况。不知道为什么。另一种情况是,似乎没有办法让端口或连接的设备报告队列中有多少完全终止的线路。这是真的吗?不知道。只是没有找到办法。所以,它是 bytes 。好吧,我只想要我的狗狗数据,但是我可以得到它,并且知道它们都不会被篡改。

所以,我正在通过串口读取我正在做的以下内容,以应对我所嘀咕的一切:

###        CONDITION FIRST CHANNEL BYTE-STRING DATA FOR ANALYSIS

#Decode to asii 
MRDs1 = MRD1.decode('ascii')

#Add previous non-terminated 'orphan' data to the recent chunk of data
S1 = orphan1 + MRDs1

#Normalize non-numeric characters to * delimiter. What a mess...
SD1 = S1.replace("\r\n","*").replace("\r","").replace("\n","").split("*")

#Assess data stream for new non-terminated entry
orphan1 = ""
if len(SD1[len(SD1)-1]) == 0:
    del SD1[len(SD1)-1]
elif len(SD1[len(SD1)-1]) <6: #this '6' is only for my particular case.
    orphan1 = SD1.pop() #Is this the best way to knock-off orphan bytes?

#Check for meaningless/null leading data (might not even be necessary)
if len(SD1[0])<6: #Same drill as above, but on the front end.
    del SD1[0] #Is this really how it's best done in python?

#Extract numerical integer value list
ND1 = list(map(int,SD1))
当然,

主循环内部。从那里,ND1(&#34;通道-1新数据&#34; - 我有多达四个通道)被发送到用于FFT的环形缓冲区(不是我们在这里所说的,但是一个很棒的话题独自)。

所以,我真正感到有启发性和我肯定会欣赏的,我希望,这个小主题的其他读者,如果有经验的社区成员可以提供有关的见解或建议。我上面粘贴了什么。批评也绝对赞赏。扔西红柿,只要它们是球形的。我是一名物理学家。不是真正的编码器。要清楚,是的,这种方法现在正在工作。它永远不会错过数据点。当然,但它是最佳的吗?我不知道。可能不是。我所做的一切都不是最佳选择。它是否尽可能快地使用Python?我对此表示怀疑。回想一下,我在Raspberry Pi-3上,所以我在寻求效率。同样的问题困扰着我对FFT的使用(我使用numpy rfft。这甚至更好吗?)和我的情节更新(Geez,我在matplotlib中的FFT图看起来很慢。)。无论如何,我认为我的Python技能已经成熟,需要改进。谢谢,如果你能帮我那么做。无论如何,我打算在这个帖子结束时发布我/我们的完整代码,无论好坏,希望能帮助下一个 unbeliever 脱离死亡中心,在那里我无休止地居住。我会给它几天......