You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中用Paramiko实现XML-RPC over SSH报错:Transport无request属性

实现XML-RPC over SSH(Paramiko+xmlrpc)的正确方案

问题背景

尝试用Paramiko实现XML-RPC通过SSH通信时,调用XML-RPC方法触发AttributeError: 'Transport' object has no attribute 'request'错误。网络连接和库安装正常,SSH连接可建立,但Paramiko返回的Transport对象与xmlrpc.client要求的Transport接口不兼容。

错误原因

xmlrpc.client.ServerProxy的transport参数需要的是实现了xmlrpc.client.Transport抽象接口的对象(必须包含request方法),而Paramiko的Transport是SSH传输层控制对象,两者接口完全不同,直接传入会导致调用未定义方法的错误。

解决方案1:SSH端口转发(推荐,实现简单)

通过SSH建立本地端口到远程XML-RPC服务端口的转发,让本地XML-RPC客户端连接本地转发端口,间接访问远程服务。

修改后的客户端代码

import paramiko
import xmlrpc.client
import getpass

# 配置参数
REMOTE_HOST = "your_hostname"
REMOTE_XMLRPC_PORT = 8000  # 远程XML-RPC服务监听的端口
LOCAL_FORWARD_PORT = 9000  # 本地映射端口
USERNAME = "username"
PASSWORD = getpass("Enter password:")

# 初始化SSH客户端
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.connect(REMOTE_HOST, username=USERNAME, password=PASSWORD)

# 建立端口转发:本地LOCAL_FORWARD_PORT -> 远程127.0.0.1:REMOTE_XMLRPC_PORT
# 注意:如果远程XML-RPC服务绑定的是0.0.0.0,这里可以用REMOTE_HOST,否则用127.0.0.1
ssh.get_transport().open_channel(
    'direct-tcpip',
    ('127.0.0.1', REMOTE_XMLRPC_PORT),
    ('127.0.0.1', LOCAL_FORWARD_PORT)
)

# 连接本地转发端口,发起XML-RPC请求
xmlrpc_client = xmlrpc.client.ServerProxy(f"http://127.0.0.1:{LOCAL_FORWARD_PORT}")
result = xmlrpc_client.your_method_name()
print(result)

# 关闭连接
ssh.close()

服务器端代码(无需修改,注意绑定地址)

如果远程XML-RPC服务只监听127.0.0.1,端口转发刚好能访问;如果要允许外部访问,可以修改绑定地址为0.0.0.0:

from xmlrpc.server import SimpleXMLRPCServer

# 绑定0.0.0.0允许所有地址访问,或者127.0.0.1仅本地访问
server = SimpleXMLRPCServer(("0.0.0.0", 8000))

def your_method_name():
    return "hello, world!"
server.register_function(your_method_name)

server.serve_forever()

解决方案2:自定义XML-RPC Transport(基于Paramiko通道)

实现一个符合xmlrpc.client.Transport接口的自定义类,使用Paramiko的SSH通道来传输XML-RPC请求和响应。

自定义Transport类及客户端代码

import paramiko
import xmlrpc.client
import getpass
from io import BytesIO

class SSHXMLRPCTransport(xmlrpc.client.Transport):
    def __init__(self, ssh_client, remote_host, remote_port):
        super().__init__()
        self.ssh_client = ssh_client
        self.remote_host = remote_host
        self.remote_port = remote_port
        self.channel = None

    def make_connection(self, host):
        # 建立SSH通道连接到远程XML-RPC端口
        self.channel = self.ssh_client.get_transport().open_channel(
            'direct-tcpip',
            (self.remote_host, self.remote_port),
            ('127.0.0.1', 0)
        )
        return self

    def send_request(self, host, handler, request_body, debug):
        # 发送XML-RPC请求
        self.channel.send(request_body)
        # 读取响应(简单实现,实际可根据需求优化分块逻辑)
        response = b""
        while not self.channel.closed:
            chunk = self.channel.recv(4096)
            if not chunk:
                break
            response += chunk
        return response

    def parse_response(self, response):
        # 解析XML-RPC响应
        return super().parse_response(BytesIO(response))

# 配置参数
REMOTE_HOST = "your_hostname"
REMOTE_XMLRPC_PORT = 8000
USERNAME = "username"
PASSWORD = getpass("Enter password:")

# 初始化SSH客户端
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.connect(REMOTE_HOST, username=USERNAME, password=PASSWORD)

# 使用自定义Transport创建XML-RPC客户端
transport = SSHXMLRPCTransport(ssh, REMOTE_HOST, REMOTE_XMLRPC_PORT)
xmlrpc_client = xmlrpc.client.ServerProxy(f"http://{REMOTE_HOST}:{REMOTE_XMLRPC_PORT}", transport=transport)

# 调用方法
result = xmlrpc_client.your_method_name()
print(result)

# 关闭资源
transport.channel.close()
ssh.close()

内容的提问来源于stack exchange,提问作者bblais

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 05:31:33