Weibw's World Weibw's World
首页
  • HTML
  • Python

    • Python基础知识
    • Python CookBook第三版
    • Flask
  • MySQL

    • MySQL基础知识
    • MySQL调优
    • MySQL面试题
算法
  • FineReport
  • Kettle
  • Git
  • 微信公众号文章
  • 优秀博客文章
  • 其他
收藏夹
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Weibw

一个没有梦想的咸鱼
首页
  • HTML
  • Python

    • Python基础知识
    • Python CookBook第三版
    • Flask
  • MySQL

    • MySQL基础知识
    • MySQL调优
    • MySQL面试题
算法
  • FineReport
  • Kettle
  • Git
  • 微信公众号文章
  • 优秀博客文章
  • 其他
收藏夹
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 《Flask》

  • 《Python Cookbook》第三版

    • 第一章:数据结构与算法

    • 第二章:字符串和文本

    • 第三章:数字日期和时间

    • 第四章:迭代器与生成器

    • 第五章:文件与IO

    • 第六章:数据编码和处理

    • 第七章:函数

    • 第八章:类与对象

    • 第九章:元编程

    • 第十章:模块与包

    • 第十一章:网络与Web编程

      • 作为客户端与HTTP服务交互
      • 创建TCP服务器
      • 创建UDP服务器
      • 通过CIDR地址生成对应的IP地址集
      • 创建一个简单的REST接口
      • 通过XML-RPC实现简单的远程调用
      • 在不同的Python解释器之间交互
        • 问题
        • 解决方案
        • 讨论
      • 实现远程方法调用
      • 简单的客户端认证
      • 在网络服务中加入SSL
      • 进程间传递Socket文件描述符
      • 理解事件驱动的IO
      • 发送与接收大型数组
    • 第十二章:并发编程

    • 第十三章:脚本编程与系统管理

    • 第十四章:测试、调试和异常

    • 第十五章:C语言扩展

  • Python基础

  • Python
  • 《Python Cookbook》第三版
  • 第十一章:网络与Web编程
weibw
2022-01-18

在不同的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')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

然后客户端连接服务器并发送消息的简单示例:

>>> from multiprocessing.connection import Client
>>> c = Client(('localhost', 25000), authkey=b'peekaboo')
>>> c.send('hello')
>>> c.recv()
'hello'
>>> c.send(42)
>>> c.recv()
42
>>> c.send([1, 2, 3, 4, 5])
>>> c.recv()
[1, 2, 3, 4, 5]
>>>
1
2
3
4
5
6
7
8
9
10
11
12

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

# 讨论

目前有很多用来实现各种消息传输的包和函数库,比如 ZeroMQ、Celery 等。 你还有另外一种选择就是自己在底层 socket 基础之上来实现一个消息传输层。 但是你想要简单一点的方案,那么这时候 multiprocessing.connection 就派上用场了。 仅仅使用一些简单的语句即可实现多个解释器之间的消息通信。

如果你的解释器运行在同一台机器上面,那么你可以使用另外的通信机制,比如 Unix 域套接字或者是 Windows 命名管道。 要想使用 UNIX 域套接字来创建一个连接,只需简单的将地址改写一个文件名即可:

s = Listener('/tmp/myconn', authkey=b'peekaboo')
1

要想使用 Windows 命名管道来创建连接,只需像下面这样使用一个文件名:

s = Listener(r'\\.\pipe\myconn', authkey=b'peekaboo')
1

一个通用准则是,你不要使用 multiprocessing 来实现一个对外的公共服务。 Client() 和 Listener() 中的 authkey 参数用来认证发起连接的终端用户。 如果密钥不对会产生一个异常。此外,该模块最适合用来建立长连接(而不是大量的短连接), 例如,两个解释器之间启动后就开始建立连接并在处理某个问题过程中会一直保持连接状态。

如果你需要对底层连接做更多的控制,比如需要支持超时、非阻塞 I/O 或其他类似的特性, 你最好使用另外的库或者是在高层 socket 上来实现这些特性。

编辑 (opens new window)
上次更新: 2023/10/13, 17:39:25
通过XML-RPC实现简单的远程调用
实现远程方法调用

← 通过XML-RPC实现简单的远程调用 实现远程方法调用→

最近更新
01
牛客网非技术快速入门SQL练习题
03-08
02
其他日常SQL题
03-07
03
用户与权限管理
03-05
更多文章>
Theme by Vdoing | Copyright © 2021-2023 | Weibw | 辽ICP备18015889号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式