在Python中将UDP数据写入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

免责声明:我完全是PythonN00B,从来没有用Python写过任何东西,我已经好几年没有编写过任何程序,我最后学的语言是VisualBasic6。所以请容忍我

因此,我有一个Android应用程序,通过UDP将手机的传感器(加速计、磁铁、灯光等)数据传输到我的Windows PC,我有一个Python 3.3脚本在屏幕上显示这些数据,并将其写入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
需要一个序列或可编辑的值。但你只有一个价值

它之所以能正常工作,但却做了错误的事情,是因为你的一个值&a
bytes
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()