使用PyZMQ

时间:2018-04-29 19:36:16

标签: python pyzmq

我有一个客户端应用程序,它将消息发送到远程服务器,消息从服务器处理,结果发送回客户端。

简化示例如下:

client.py

import zmq
def get_message(msg, ip, port, socket, send_socket_type='pyobj'):
    socket.connect("tcp://%s:%s" % (ip, port))
    socket.send_string(msg)
    if send_socket_type=='pyobj':
        msg = socket.recv_pyobj()
    if send_socket_type=='string':
        msg = socket.recv_string()
    if send_socket_type=='json':
        msg = socket.recv_json()
    return msg
    socket.close()

server.py

import zmq
import time

port=9999
context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("tcp://*:%s" % port)


def processmessage(msg):
    for i in range(10):
        print(i)
        time.sleep(1)
    return msg

while True:
    msg = socket.recv()
    print('message received from client:', msg)
    cmd = processmessage(msg)
    socket.send_pyobj(cmd)
    print('sending to client: %s ' % msg)
    time.sleep(0.2)

测试

server_env={'IP': ip, 'PORT': port}

context = zmq.Context()
socket = context.socket(zmq.REQ)

messages = ['first message', 'second message', 'third message']

for i in messages:
  msg = get_message('message', ip=server_env['IP'], port=server_env['PORT'], socket)
  print(msg)

我的问题:

  • 如何扩展这个简单的客户端 - 服务器示例,以允许客户端接收运行服务器端的进程processmessage()生成的标准输出?

1 个答案:

答案 0 :(得分:1)

您可以在处理消息时使用上下文管理器将sys.stdout重定向到StringIO对象:

from contextlib import contextmanager
import io
import sys

@contextmanager
def capture():
    save_stdout = sys.stdout
    sys.stdout = io.StringIO()
    try:
        yield sys.stdout
    finally:
        sys.stdout = save_stdout


def processmessage(msg):
    with capture() as stdout:
        for i in range(10):
            print(i)
            time.sleep(1)
    return {
        'reply': msg,
        'stdout': stdout.getvalue(),
    }

使用此上下文管理器可以在任何代码块中捕获stdout,并在上下文结束后通过stdout.getvalue()检索stdout上发生的任何输出。然后,您可以使用两个字段发送回复:结果本身和处理期间捕获的标准输出。

如果您感兴趣,可以通过以下方式对stderr执行相同操作:

  1. 将stderr重定向到相同的StringIO对象,因此将stdout / err合并在一起,或
  2. 如果要将它们分开,请将stderr发送到自己的StringIO对象。