Python使用kombu连接信息中包含#号问题排查方式
作者:Chengdu.S
python 项目部署生产环境遇到一个错误问题:
raise ValueError(f"Port could not be cast to integer value as {port!r}") ValueError: Port could not be cast to integer value as 'guest
测试环境和本地调试都没有问题,但是到生产之后就有问题,本章复现有问题的mq连接配置的导致的错误信息,记录问题排查过程
版本信息
框架 | 版本 |
---|---|
python | 3.11.7 |
kombu | 5.3.4 |
环境搭建
python 虚拟环境
Python 虚拟环境(Virtual Environment)是一个隔离的 Python 解释器环境,它允许你为每个 Python 项目安装其特定的依赖包,而不会干扰到全局 Python 环境或其他项目。
这样,你可以确保每个项目都有其独立的、一致的依赖环境,避免了版本冲突和依赖混乱的问题。
Python 中有几个流行的工具用于创建和管理虚拟环境,其中最常用的是 venv 和 virtualenv
venv 创建 python 虚拟环境
python -m venv .venv
执行该命令之后,会创建一个虚拟的环境,产生 .venv文件夹, 目录结构如下
激活虚拟环境
.venv\Scripts\activate
激活虚拟环境之后,文件夹前面会有括号显示虚拟环境的名称
退出虚拟环境
deactivate
虚拟环境下查看python、pip版本
查询pip 配置信息
(.venv) F:\Python\mq>pip config list global.index-url='http://mirrors.aliyun.com/pypi/simple/' install.trusted-host='mirrors.aliyun.com'
安装依赖
编写 requirements.txt
kombu==5.3.4
在虚拟环境里面安装依赖
pip install -r requirements.txt
问题复现以及问题排查
1.消息发布端 hello_publisher.py
from __future__ import annotations import datetime from kombu import Connection with Connection('amqp://guest:guest#2024@localhost:5672//') as conn: simple_queue = conn.SimpleQueue('simple_queue') message = f'helloworld, sent at {datetime.datetime.today()}' simple_queue.put(message) print(f'Sent: {message}') simple_queue.close()
2.在虚拟环境运行代码
出现如下报错信息
(.venv) F:\Python\mq>python hello_publisher.py
Traceback (most recent call last):
File "F:\Python\mq\hello_publisher.py", line 7, in <module>
with Connection('amqp://guest:guest#2024@localhost:5672//') as conn:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "F:\Python\mq\.venv\Lib\site-packages\kombu\connection.py", line 203, in __init__
url_params = parse_url(hostname)
^^^^^^^^^^^^^^^^^^^
File "F:\Python\mq\.venv\Lib\site-packages\kombu\utils\url.py", line 38, in parse_url
scheme, host, port, user, password, path, query = _parse_url(url)
^^^^^^^^^^^^^^^
File "F:\Python\mq\.venv\Lib\site-packages\kombu\utils\url.py", line 70, in url_to_parts
parts.port,
^^^^^^^^^^
File "E:\Anaconda\Lib\urllib\parse.py", line 182, in port
raise ValueError(f"Port could not be cast to integer value as {port!r}")
ValueError: Port could not be cast to integer value as 'guest'
看到报错的堆栈信息,首先定位到代码行
File "F:\Python\mq\.venv\Lib\site-packages\kombu\utils\url.py", line 70
在此处加一个断点,调试一下(生产服务不能调试就print输出一下信息)
3.调试出问题的代码
报错的代码方法如下
def url_to_parts(url): # type: (str) -> urlparts """Parse URL into :class:`urlparts` tuple of components.""" scheme = urlparse(url).scheme schemeless = url[len(scheme) + 3:] # parse with HTTP URL semantics parts = urlparse('http://' + schemeless) path = parts.path or '' path = path[1:] if path and path[0] == '/' else path return urlparts( scheme, unquote(parts.hostname or '') or None, parts.port, unquote(parts.username or '') or None, unquote(parts.password or '') or None, unquote(path or '') or None, dict(parse_qsl(parts.query)), )
parts.port 获取的值从 urlparse 方法中解析出来的
执行完 urlparse 方法之后获取到的数值如下
port 的解析在 urlparse 这一步出了问题,重点来看看这个方法的逻辑
经过调试发现问题出在切割方法里面 urllib.parse.urlsplit
,具体处理出问题代码在如下片段
链接中有 # 号导致切割之后端口号错位未获取到
去除链接中的#号的正常解析的数据如下
链接中没有 # 号之后,端口可以正常解析了
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。