在Python中将UDP数据写入CSV?
免责声明:我完全是PythonN00B,从来没有用Python写过任何东西,我已经好几年没有编写过任何程序,我最后学的语言是VisualBasic6。所以请容忍我 因此,我有一个Android应用程序,通过UDP将手机的传感器(加速计、磁铁、灯光等)数据传输到我的Windows PC,我有一个Python 3.3脚本在屏幕上显示这些数据,并将其写入CSV:在Python中将UDP数据写入CSV?,python,csv,encoding,udp,ascii,Python,Csv,Encoding,Udp,Ascii,免责声明:我完全是PythonN00B,从来没有用Python写过任何东西,我已经好几年没有编写过任何程序,我最后学的语言是VisualBasic6。所以请容忍我 因此,我有一个Android应用程序,通过UDP将手机的传感器(加速计、磁铁、灯光等)数据传输到我的Windows PC,我有一个Python 3.3脚本在屏幕上显示这些数据,并将其写入CSV: #include libraries n stuff import socket import traceback import csv
#include libraries n stuff
import socket
import traceback
import csv
#assign variables n stuff
host = ''
port = 5555
csvf = 'accelerometer.csv'
#do UDP stuff
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.bind((host, port))
#do CSV stuff
with open(csvf, 'w', newline='', encoding='ascii') as csv_handle:
csv_writer = csv.writer(csv_handle, delimiter=',')
while 1:
try:
message, address = s.recvfrom(8192)
print(message) #display data on screen
csv_writer.writerow(message) #write data to CSV
except(KeyboardInterrupt, SystemExit):
raise
except:
traceback.print_exc()
屏幕上的数据如下所示,这是正确的:
b'7407.75961, 3, 0.865, 1.423, 9.022, 5,
CSV文件中的数据看起来像数据的ASCII代码的数值(注意:代码与上面的代码不匹配,因为数据略有不同):
如何让CSV只写入UDP套接字接收的字符串?如您所见,我尝试添加“encoding='ascii'”,但这与省略它没有什么区别。尝试:
csv_writer.writerow([message])
csv\u writer.writerow
需要一个iterable作为其第一个参数,即逗号分隔的值列表。在您的示例中,消息是可编辑的字符串,因此csv_编写器将每个字符写入单独的逗号分隔值。writerow
需要一个序列或可编辑的值。但你只有一个价值
它之所以能正常工作,但却做了错误的事情,是因为你的一个值&abytes
string本身就是一个序列。但它不是一个逗号分隔的值序列,而是一个字节序列
那个么,如何得到一系列独立的值呢
一个选项是使用
split
。无论是message.split(b',')
还是map(str.strip,message.split(b','))
在这里似乎都是合理的。这将为您提供以下序列:
[b'7407.75961', b'3', b'0.865', b'1.423', b'9.022', b'5']
但实际上,这正是
csv
模块的用途。例如,您可以将输入包装在字节IO
中,并将其传递给csv.reader
,然后您只需将该读取器中的行复制到编写器中即可
但是如果你仔细想想,你得到的是csv
格式的数据,你想用完全相同的csv
格式写出来,而不以任何其他方式使用它……所以你甚至不需要这里的csv
模块。只需使用普通的旧二进制文件:
with open(csvf, 'wb') as csv_handle:
while True:
try:
message, address = s.recvfrom(8192)
print(message) #display data on screen
csv_handle.write(message + b'\n')
except(KeyboardInterrupt, SystemExit):
raise
except:
traceback.print_exc()
当我们这样做时,您几乎不需要这样做:
except(KeyboardInterrupt, SystemExit):
raise
except:
traceback.print_exc()
Python3.x中唯一不从异常继承的异常是键盘中断
,系统退出
,GeneratorExit
(此处不可能发生),以及任何第三方异常,它们的行为方式类似于键盘中断
和系统退出
。所以,只要这样做:
except Exception:
traceback.print_exc()
万岁!非常感谢。实际上我有:csv_writer.writerow(message.decode(encoding='ascii')),所以我把它改为:csv_writer.writerow([message.decode(encoding='ascii')]),它成功了!酷,这可能是一个更好的方法!如果有人想帮我编写代码,现在还有两件事要做:1:不要写空格,导入CSV时会混淆Excel,所以用null替换UDP数据中的空格?2:如何定期写入文件,以防PC崩溃?这个程序将运行8小时,生成一个30mb的CSV文件!A) 如果我试图在结尾一次写下所有的内容,这可能是行不通的,而且b)这不是一种非常可靠的做事方式。谢谢你的帮助!(1) 嗯,空('\0'
)会使Excel更加混乱……但是空字符串,是的。确保message.replace(“,”,“,”,“)
确实删除了所有正确的空格,而没有其他任何内容……如果简单的东西可以工作,请使用它。如果第一次尝试时发现它太奇怪,我会继续使用csv
解析它,然后再次使用csv
以Excel想要的不同行格式将其写出。(2)无论哪种方式,您都已经在周期性地写入文件,而不是在最后。但是,如果您不调用flush
或close
,则这些写入操作可能会在崩溃期间丢失。因此,只要在每次写入之后或在每次N次写入之后调用flush
,或者如果上次刷新之后已经过了X秒,或者在性能和健壮性之间进行任何看起来最好的权衡。(你可以每次打开和关闭文件,甚至写一个新的副本,然后每次都将其移到原始文件上,这样可以保证你不会在断电后只剩下半行,但这可能是过分的。)(2)你的评论暗示你可能只想定期写,而不是每次收到信息都写。这可以提高性能,但会使事情变得更加复杂,这意味着您将面临更多数据丢失的风险。Python和您的操作系统所做的缓冲已经足够好了,只要立即编写并推迟刷新,就可以在不增加成本的情况下获得最大的性能优势?我还没有测试它很长时间,但我已经达到了250kB,在我关闭程序之前,我从来没有看到过写入的文件(在Windows资源管理器中按F5进行检查)。
except Exception:
traceback.print_exc()