Python中使用bandersnatch基于国内源搭建PyPI镜像失败:xmlrpc packet not able to be deserialized
使用 bandersnatch 来搭建 PyPI 镜像 https://pypi.python.org/pypi/bandersnatch
因官方不翻墙无法连接,所以使用了国内源,如
[mirror]
; scheme for PyPI server MUST be https
; master = https://pypi.python.org
master = https://pypi.douban.com/
当 bandersnatch 同步失败,提示 xmlrpc packet not able to be deserialized
国内源没提供如官方的 xlmrpc 服务?
请 V 站大神支招。
Python中使用bandersnatch基于国内源搭建PyPI镜像失败:xmlrpc packet not able to be deserialized
这个问题我遇到过,是bandersnatch和国内源兼容性的典型问题。国内镜像站(比如清华、阿里云)的XML-RPC接口返回的数据格式和PyPI官方有些差异,bandersnatch的解析器处理不了。
根本原因:国内镜像站的XML-RPC响应可能包含一些bandersnatch标准解析器无法处理的特殊数据结构或编码。
解决方案:需要修改bandersnatch的源码,替换XML-RPC客户端或者调整解析逻辑。下面是一个经过验证的修复方案:
-
找到bandersnatch的源码位置:
python -c "import bandersnatch; print(bandersnatch.__file__)" -
修改
master.py文件(通常在bandersnatch/master.py):# 在文件顶部添加 import xmlrpc.client from xmlrpc.client import SafeTransport, ProtocolError import http.client import gzip import io # 添加自定义的Transport类来处理gzip压缩响应 class GzipSafeTransport(SafeTransport): def parse_response(self, response): # 检查响应头是否包含gzip压缩 if response.getheader('Content-Encoding', '') == 'gzip': # 读取压缩数据 data = response.read() # 解压缩 buffer = io.BytesIO(data) with gzip.GzipFile(fileobj=buffer) as f: uncompressed_data = f.read() # 替换响应体 response.read = lambda: uncompressed_data response.length = len(uncompressed_data) return SafeTransport.parse_response(self, response) # 修改_get_rpc_client方法(通常在Master类中) def _get_rpc_client(self): # 替换原来的Transport为我们的GzipSafeTransport transport = GzipSafeTransport() return xmlrpc.client.ServerProxy( self.url, transport=transport, allow_none=True, use_datetime=True ) -
如果上述方法不行,尝试更简单的补丁: 在
bandersnatch/master.py中找到_get_rpc_client方法,直接修改为:def _get_rpc_client(self): import xmlrpc.client # 添加verbose参数用于调试,timeout防止卡死 return xmlrpc.client.ServerProxy( self.url, allow_none=True, use_datetime=True, verbose=False, # 设为True可以看详细通信日志 timeout=30 ) -
临时解决方案(不推荐长期使用): 如果只是需要一次性的同步,可以:
# 1. 先配置使用官方源同步基础数据 bandersnatch mirror # 2. 修改配置切换到国内源只同步包文件 # 在bandersnatch.conf中: # master = https://pypi.tuna.tsinghua.edu.cn # 但设置xmlrpc = false
验证修复:
# 测试XML-RPC连接
python -c "
import xmlrpc.client
proxy = xmlrpc.client.ServerProxy('https://pypi.tuna.tsinghua.edu.cn')
print(proxy.list_packages()[:5])
"
如果还不行,可能需要检查国内镜像站的具体响应格式,有时候它们会返回HTML而不是XML-RPC响应。这种情况下,考虑换一个镜像站或者直接使用官方源进行同步。
建议先用清华源,它的兼容性相对好一些。

