#!coding=utf-8
"""
    在不同的Python解释器之间交互
"""
# 你在不同的机器上面运行着多个Python解释器实例，并希望能够在这些解释器之间通过消息来交换数据。

# 通过使用 multiprocessing.connection 模块可以很容易的实现解释器之间的通信。 下面是一个
# 简单的应答服务器例子：
from multiprocessing.connection import Listener
import traceback


def echo_client(conn):
    try:
        while True:
            msg = conn.recv()
            conn.send(msg)
    except EOFError:
        print("Connection closed")


def echo_server(address, authkey):
    serv = Listener(address, authkey=authkey)
    while True:
        try:
            client = serv.accept()
            echo_client(client)
        except Exception:
            traceback.print_exc()


echo_server(("", 25000), authkey=b"peekaboo")

# 跟底层socket不同的是，每个消息会完整保存（每一个通过send()发送的对象能通过recv()来完整接受）。 另外，
# 所有对象会通过pickle序列化,需要自己先pickle序列化后再传输。因此，任何兼容pickle的对象都能
# 在此连接上面被发送和接受。

# 目前有很多用来实现各种消息传输的包和函数库，比如ZeroMQ、Celery等。 你还有另外一种选择就是
# 自己在底层socket基础之上来实现一个消息传输层。 但是你想要简单一点的方案，那么这时候
# multiprocessing.connection 就派上用场了。 仅仅使用一些简单的语句即可实现多个解释器之间
# 的消息通信。
#
# 如果你的解释器运行在同一台机器上面，那么你可以使用另外的通信机制，比如Unix域套接字或者
# 是Windows命名管道。 要想使用UNIX域套接字来创建一个连接，只需简单的将地址改写一个
# 文件名即可：
# s = Listener('/tmp/myconn', authkey=b'peekaboo')

# 要想使用Windows命名管道来创建连接，只需像下面这样使用一个文件名：
# s = Listener(r'\\.\pipe\myconn', authkey=b'peekaboo')

# 一个通用准则是，你不要使用 multiprocessing 来实现一个对外的公共服务。 Client() 和
# Listener() 中的 authkey 参数用来认证发起连接的终端用户。 如果密钥不对会产生一个异常。
# 此外，该模块最适合用来建立长连接（而不是大量的短连接）， 例如，两个解释器之间启动后
# 就开始建立连接并在处理某个问题过程中会一直保持连接状态。
#
# 如果你需要对底层连接做更多的控制，比如需要支持超时、非阻塞I/O或其他类似的特性，
# 你最好使用另外的库或者是在高层socket上来实现这些特性。