在python异步IO上发布订阅
我认为我的问题很简单也很愚蠢,但我读了很多资料,无法想象如何做我想做的事 所以,我使用在python异步IO上发布订阅,python,websocket,python-asyncio,Python,Websocket,Python Asyncio,我认为我的问题很简单也很愚蠢,但我读了很多资料,无法想象如何做我想做的事 所以,我使用websockets库,我有一个算法: # 1. get connection and start handle it async def main_request_handler(ws, path): proxy = Proxy() try: await proxy.start(ws, path) 二,。在start内部,我创建第二个websocket来传递来自ws的请求,并
websockets
库,我有一个算法:
# 1. get connection and start handle it
async def main_request_handler(ws, path):
proxy = Proxy()
try:
await proxy.start(ws, path)
二,。在start内部,我创建第二个websocket来传递来自ws
的请求,并接收应答,将它们发送到ws
while True:
request_raw = await self.ws_server.recv()
await self.process_request_from_server(request_raw)
问题是,我需要使用一个websocket服务器连接进行复制
ws
客户端,我需要从ws\u服务器
向每个人传递相同的答案。现在我只得到一个响应,因为.recv()只返回其中一个“订阅者”的值。
如何解决这个问题?请注意,我使用的是
,而True
和async
我不确定我是否理解正确,但多个协程不是你想要的吗
while True:
request_raw = await self.ws_server.recv()
# process by multiple clients parallely:
await asyncio.gather(
self.process_by_client_1(request_raw),
self.process_by_client_2(request_raw),
self.process_by_client_3(request_raw),
)
我不确定我是否理解正确,但多个协同程序不是你想要的吗
while True:
request_raw = await self.ws_server.recv()
# process by multiple clients parallely:
await asyncio.gather(
self.process_by_client_1(request_raw),
self.process_by_client_2(request_raw),
self.process_by_client_3(request_raw),
)
下面是一个非常简单的发布/订阅websockets服务器示例
import asyncio
import websockets
connections = set()
n = 0
async def handler(websocket, path):
global n
if path == "/sub":
n = n + 1
i = n
connections.add(websocket)
print("adding subscriber #", i)
try:
async for msg in websocket:
pass # ignore
except websockets.ConnectionClosed:
pass
finally:
print("removing subscriber #", i)
connections.remove(websocket)
elif path == "/pub":
async for msg in websocket:
print("<", msg)
for ws in connections:
asyncio.ensure_future(ws.send(msg))
start_server = websockets.serve(handler, 'localhost', 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
下面是一个非常简单的发布/订阅websockets服务器示例
import asyncio
import websockets
connections = set()
n = 0
async def handler(websocket, path):
global n
if path == "/sub":
n = n + 1
i = n
connections.add(websocket)
print("adding subscriber #", i)
try:
async for msg in websocket:
pass # ignore
except websockets.ConnectionClosed:
pass
finally:
print("removing subscriber #", i)
connections.remove(websocket)
elif path == "/pub":
async for msg in websocket:
print("<", msg)
for ws in connections:
asyncio.ensure_future(ws.send(msg))
start_server = websockets.serve(handler, 'localhost', 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
换句话说,我需要与多个使用者在同一个循环和线程中运行
.recv
。在RxPy中,我可以stream.emit(recv\u result)
并使用类似thatstrem.subscribe(callback\u fn)
的项目,但这是回调方式,我需要异步
您的subscribe
方法可以接受协同路由函数,即使用async def
创建的函数。一旦有东西发出,就可以使用create\u task
实例化它们并生成它们的协同程序:
def __init__(self, ...):
self._subscribers = []
def subsribe(self, corofn):
self._subscribers.append(corofn)
def emit(self, obj):
loop = asyncio.get_event_loop()
for corofn in self._subscribers:
coro = corofn(obj)
loop.create_task(coro)
async def main(self):
while True:
request_raw = await self.ws_server.recv()
self.emit(request_raw)
换句话说,我需要与多个使用者在同一个循环和线程中运行
.recv
。在RxPy中,我可以stream.emit(recv\u result)
并使用类似thatstrem.subscribe(callback\u fn)
的项目,但这是回调方式,我需要异步
您的subscribe
方法可以接受协同路由函数,即使用async def
创建的函数。一旦有东西发出,就可以使用create\u task
实例化它们并生成它们的协同程序:
def __init__(self, ...):
self._subscribers = []
def subsribe(self, corofn):
self._subscribers.append(corofn)
def emit(self, obj):
loop = asyncio.get_event_loop()
for corofn in self._subscribers:
coro = corofn(obj)
loop.create_task(coro)
async def main(self):
while True:
request_raw = await self.ws_server.recv()
self.emit(request_raw)
谢谢你的建议,它们可能有用。我排起队来了
class SWebsocket(object):
def __init__(self, websocket: WebSocketServerProtocol):
self.ws = websocket
self.queues = {}
self.subscribe()
def subscribe(self):
# fire and forget function
asyncio.ensure_future(self.recv_mess())
async def recv_mess(self):
while True:
try:
data = await self.ws.recv()
except websockets.ConnectionClosed as e:
for _, q in self.queues.items():
await q.put(e)
return
for _, q in self.queues.items():
await q.put(data)
async def recv(self, id):
# read value from queue
if id not in self.queues:
self.queues[id] = asyncio.Queue()
data = await self.queues[id].get()
if isinstance(data, websockets.ConnectionClosed):
raise data
return data
谢谢你的建议,它们可能有用。我排起队来了
class SWebsocket(object):
def __init__(self, websocket: WebSocketServerProtocol):
self.ws = websocket
self.queues = {}
self.subscribe()
def subscribe(self):
# fire and forget function
asyncio.ensure_future(self.recv_mess())
async def recv_mess(self):
while True:
try:
data = await self.ws.recv()
except websockets.ConnectionClosed as e:
for _, q in self.queues.items():
await q.put(e)
return
for _, q in self.queues.items():
await q.put(data)
async def recv(self, id):
# read value from queue
if id not in self.queues:
self.queues[id] = asyncio.Queue()
data = await self.queues[id].get()
if isinstance(data, websockets.ConnectionClosed):
raise data
return data
你能发布一个
最简单的例子吗?所以我可以试试你的代码吗?这将是一个相当大的例子,你可能需要将问题抽象到你正在努力解决的特定部分。如果它是非常特定于领域的,其他人将无法理解代码的意图。这可能是一个挑战……你能发布一个最简单的例子吗?所以我可以试试你的代码吗?这将是一个相当大的例子,你可能需要将问题抽象到你正在努力解决的特定部分。如果它是非常特定于领域的,其他人将无法理解代码的意图。这可能是一个挑战…是的,我想要这样的东西,但我需要动态地添加process\u by\u client\u
。(如添加回调,但我需要使用wait
关键字运行它。换句话说,我需要在同一个循环和线程中与多个使用者一起运行.recv
。在RxPy中,我可以只stream.emit(recv_result)
并使用类似于strem.subscribe(callback\fn)的项)
,但这是回调方式,我需要异步是的,我想要类似的东西,但我需要动态添加process\u by\u client\u
。(比如添加回调,但我需要使用wait
关键字运行它。换句话说,我需要在同一个循环和线程中与多个使用者一起运行.recv
。在RxPy中,我可以只stream.emit(recv_result)
并使用类似strem.subscribe(callback\fn)
,但这是回调方式,我需要异步。)