通过python websocket重放基于计时器的数据
目前,我正在开发一个IoT模拟客户端,该客户端读取两个真实世界的timeseries数据CSV,并根据它们的时间戳和系统时钟(“代码>线程化”模块)“重放”它们 所以基本上我有一个Pandas数据框,它保存所有旧数据,还有一个timer tick handler函数,它从中提取相应的行,将它们提供给任何数据接收器 如果我的计时器勾号处理程序使用通过python websocket重放基于计时器的数据,python,websocket,python-asyncio,Python,Websocket,Python Asyncio,目前,我正在开发一个IoT模拟客户端,该客户端读取两个真实世界的timeseries数据CSV,并根据它们的时间戳和系统时钟(“代码>线程化”模块)“重放”它们 所以基本上我有一个Pandas数据框,它保存所有旧数据,还有一个timer tick handler函数,它从中提取相应的行,将它们提供给任何数据接收器 如果我的计时器勾号处理程序使用requests.post(..然后只将从df[..]收集的文本正文发布到\u csv(),则此功能非常有效 现在我想将这些数据流式传输到服务器api,因
requests.post(..
然后只将从df[..]收集的文本正文发布到\u csv()
,则此功能非常有效
现在我想将这些数据流式传输到服务器api,因此我们决定通过WebSocket而不是HTTP-REST传输数据。事情开始变得棘手。模块严重依赖于asyncio
,它需要自己的事件循环。因为我的计时器已经是一种事件循环(基于threading.timer
)我必须承认,我并不完全理解asyncio的概念,我认为这并不完全适合
至少我不知道如何将websocket.send()方法集成到我的处理程序方法中,以便它在asyncio事件循环中运行
DataFrame.to_csv(…可以提供一个文件处理程序file_或_buf
,我更希望像文件处理程序一样使用websocket,并在此处提供它,以刷新我的数据
- python中是否有另一个websocket实现使用了这种范例
- 可以使用
模块来实现这一点吗?我只是弄错了吗websockets
- 我是否也必须使用asyncio实现基于时间间隔的数据发送处理程序,以便两者都在事件循环中运行
间隔秒调用方法do()
从线程导入线程,事件
类计时器(线程):
定义初始值(自,间隔=1):
线程。\uuuu初始化\uuuuu(自)
self.interval=间隔
self.stopped=Event()
def运行(自):
而不是自停。等待(自停。间隔):
self.do()
def do(自我):
打印('勾选')
def get_停止标志(自身):
自动停止返回
现在使用websockets
和asyncio
的基本代码片段是
导入异步IO
导入WebSocket
异步def hello():
uri=“ws://echo.websocket.org”
与websocket异步。作为websocket连接(uri):
等待websocket.send(thread.stream())
r=等待websocket.recv()
印刷品(r)
asyncio.get_event_loop()。运行_直到完成(hello())
我已经尝试使我的do()
methodasync
,但我无法在asyncio事件循环中初始化我的TimeTicker
类,因此方法调用被“等待”
为了清楚起见,我想在TimeTicker对象外部初始化websocket连接(它应该每秒只提供timeseries数据,并将其传递给websocket.send()
。然而,我不确定这一数据传递应该发生在哪里。我的TimeTicker类也可能有更好的解决方案,每秒产生
数据,而不仅仅是调用一个方法。无论如何,我希望得到这方面的建议
提示:TimeTicker只是我的datasource类上的一个超类,它实际上包含pandas数据帧,其中包含从CSV读取的大约200.000行timeseries数据,作为要发送的存储库
解决方案:基于@wowkin2的答案我的TimeTicker类现在仅用asyncio实现了
导入异步IO
导入WebSocket
班级计时器:
is_stopped=False
定义新(cls,循环,uri,间隔=1):
instance=super()。\uuuuu new\uuuuu(cls)
instance.interval=interval
instance.uri=\u uri
instance.task=\u loop.create\u任务(instance.run())
return instance.task
异步def运行(自):
与websockets.connect(self.uri)作为self.ws异步:
尽管如此:
等待自我
等待异步睡眠(self.interval)
异步def do(自):
消息='ping'
等待self.ws.send(消息)
r=wait self.ws.recv()
印刷品(r)
def停止(自):
self.task.cancel()
self.is_stopped=True
uri=“ws://echo.websocket.org”
loop=asyncio.get\u event\u loop()
任务=计时器(循环,uri,间隔=5)
循环。运行_直到_完成(任务)
如果使用asyncio,则不需要线程模块
下面是一个如何使用asyncio定期执行某些操作的示例。
唯一的一件事——您需要有一个始终打开连接的变量,而不需要上下文管理器
import asyncio
class TimeTicker:
is_stopped = False
def __new__(cls, _loop, _ws, interval=1):
instance = super().__new__(cls)
instance.interval = interval
instance.ws = _ws
instance.task = _loop.create_task(instance.run())
return instance.task
async def run(self):
while True:
await self.do()
await asyncio.sleep(self.interval)
async def do(self):
message = 'ping'
await self.ws.send(message)
r = await self.ws.recv()
print(r)
def stop(self):
self.task.cancel()
self.is_stopped = True
uri = "ws://echo.websocket.org"
ws = websockets.connect(uri)
loop = asyncio.get_event_loop()
task = TimeTicker(loop, ws, interval=5)
loop.run_until_complete(task)
每一秒我们都会得到数据(从哪里来?)然后将其发送到web套接字?是TimeTicker。是否
获取我们需要通过web套接字发送的数据?否,因为这样它每次都会创建到websocket的新连接…我已经尝试连接外部并将连接传递到函数,但这不在循环的范围内,而且“未等待”@Hadus是的,然后通过self.dataframe在对象中可用。如果不使用线程在调用之前等待,则会更容易。您也可以在异步事件循环中等待。例如,在收到web套接字的响应后,您可以计算在再次联系web套接字之前需要等待的时间。这样,您可以我们将使用相同的连接。必须稍微采用它添加与websockets.connect(self.uri)异步作为self.ws:
在之前的一行,而为True
这样websocket连接就被初始化了。IDK为什么,但是通过构造函数传递ws
处理程序是不起作用的。整洁的类构造函数模式顺便说一句,我不知道。这对我现在运行我的东西有很大帮助!非常感谢!