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

Linux环境下Python用F-string调用SonarQube API返回404问题排查

问题:Jenkins容器中动态拼接SonarQube API参数返回404,静态值及本地环境正常
  • 在Linux Jenkins容器中,使用Python的F-string/format/字符串拼接生成pullRequest参数调用SonarQube API时,服务器返回404错误
  • 直接使用静态固定值调用该API则正常
  • Mac本地环境用同样的动态拼接方式调用API完全正常

代码示例

GERRIT_CN = os.environ.get('GERRIT_CHANGE_NUMBER')
GERRIT_PS = os.environ.get('GERRIT_PATCHSET_NUMBER')
sq_url = 'https://sonar.company.com/'
projectKey="team-pba"
gerrit_cn_ps = f"{GERRIT_CN}-{GERRIT_PS}"
print(gerrit_cn_ps)

def sonar_api():
    debug_requests_on()
    sonar = SonarQubeClient(sonarqube_url=sq_url, username=myUsr, password=myPass)
    # 静态值调用正常
    # project_pull_requests = sonar.qualitygates.get_project_qualitygates_status(projectKey="team-pba", pullRequest="124434-120") 
    # 动态拼接调用失败
    # project_pull_requests = sonar.qualitygates.get_project_qualitygates_status(projectKey=f"{projectKey}", pullRequest=f"{GERRIT_CN}-{GERRIT_PS}") 
    # project_pull_requests = sonar.qualitygates.get_project_qualitygates_status(projectKey=f"{projectKey}", pullRequest=GERRIT_CN+"-"+GERRIT_PS) 
    # project_pull_requests = sonar.qualitygates.get_project_qualitygates_status(projectKey=projectKey, pullRequest=gerrit_cn_ps) 

日志信息

失败日志(Linux Jenkins)

+ python3.8 /home/jenkins/agent/workspace/sonar-api.py
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): sonar.company.com:443
DEBUG:urllib3.connectionpool:https://sonar.company.com:443 "GET /api/qualitygates/project_status?projectKey=team-pba&pullRequest=124434-139 HTTP/1.1" 404 103
Traceback (most recent call last):
  File "/home/jenkins/agent/workspace///sonar-api.py", line 61, in <module>
    print(sonar_api())
  File "/home/jenkins/agent/workspace///sonar-api.py", line 51, in sonar_api
    project_pull_requests = sonar.qualitygates.get_project_qualitygates_status(projectKey=projectKey, pullRequest=gerrit_cn_ps)
  File "/usr/local/lib/python3.8/dist-packages/sonarqube/utils/common.py", line 132, in inner_func
    response = self._get(url_pattern, params=params)
  File "/usr/local/lib/python3.8/dist-packages/sonarqube/utils/rest_client.py", line 141, in _get
    return self.request("GET", path=path, params=params, data=data, headers=headers)
  File "/usr/local/lib/python3.8/dist-packages/sonarqube/utils/rest_client.py", line 99, in request
    raise NotFoundError(msg)
sonarqube.utils.exceptions.NotFoundError: Error in request. Possibly Not Found error [404]: Pull request '124434-139' in project 'team-pba' not found
124434-139
send: b'GET /api/qualitygates/project_status?projectKey=team-pba&amp;pullRequest=124434-139 HTTP/1.1\r\nHost: sonar.company.com\r\nUser-Agent: python-requests/2.22.0\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\nAuthorization: Basic xxxxx\r\n\r\n’
reply: 'HTTP/1.1 404 \r\n'
header: Server: nginx/1.12.2
header: Date: Tue, 28 Mar 2023 21:16:09 GMT
header: Content-Type: application/json
header: Content-Length: 103
header: Connection: keep-alive

成功日志(静态值/Linux Jenkins)

+ python3 /home/jenkins/agent/workspace/sonar-api.py
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): sonar.company.com:443
DEBUG:urllib3.connectionpool:https://sonar.company.com:443 "GET /api/qualitygates/project_status?projectKey=team-pba&amp;pullRequest=124434-139 HTTP/1.1" 200 881
[Pipeline] echo
124434-139
send: b'GET /api/qualitygates/project_status?projectKey=team-pba&amp;pullRequest=124434-139 HTTP/1.1\r\nHost
[Pipeline] }

成功日志(F-string/Mac本地)

Command> python3 sonar-api.py
all values
124434
142
124434-142
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): sonar.company.com:443
send: b'GET /api/qualitygates/project_status?projectKey=team-pba&amp;pullRequest=124434-142 HTTP/1.1\r\nHost: sonar.company.com\r\nUser-Agent: python-requests/2.27.1\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\nAuthorization: Basic xxxx\r\n\r\n’
reply: 'HTTP/1.1 200 \r\n'
header: Server: nginx/1.12.2
header: Date: Tue, 28 Mar 2023 21:53:55 GMT
header: Content-Type: application/json
header: Content-Length: 739
header: Connection: keep-alive
header: X-Frame-Options: SAMEORIGIN
header: X-XSS-Protection: 1; mode=block
header: X-Content-Type-Options: nosniff
header: Cache-Control: no-cache, no-store, must-revalidate
DEBUG:urllib3.connectionpool:https://sonar.company.com:443 "GET /api/qualitygates/project_status?projectKey=team-pba&amp;pullRequest=124434-142 HTTP/1.1" 200 739
52.53:0.0

排查方向与解决方案

核心疑点:环境变量的隐形字符

从日志看,动态拼接和静态值的请求URL表面完全一致,但结果不同,最大可能是环境变量GERRIT_CN或GERRIT_PS带有隐形空白字符(比如换行符\n、空格、制表符),导致拼接后的pullRequest参数看起来正常,实际带有不可见字符,SonarQube无法匹配到对应的PR。Jenkins环境中,环境变量可能因构建脚本输出、变量传递方式等引入隐形字符,而Mac本地环境的变量来源更干净。

验证方法

在代码中添加隐形字符检测,确认变量是否含有不可见字符:

# 打印变量原始内容和长度,检测隐形字符
print(f"GERRIT_CN raw: {repr(GERRIT_CN)}, length: {len(GERRIT_CN)}")
print(f"GERRIT_PS raw: {repr(GERRIT_PS)}, length: {len(GERRIT_PS)}")
print(f"gerrit_cn_ps raw: {repr(gerrit_cn_ps)}")

如果输出中出现'124434\n'或带空格的内容,即可确认存在隐形字符。

解决方案

对环境变量做空白字符清理,使用strip()方法去除首尾所有空白字符:

GERRIT_CN = os.environ.get('GERRIT_CHANGE_NUMBER', '').strip()
GERRIT_PS = os.environ.get('GERRIT_PATCHSET_NUMBER', '').strip()
gerrit_cn_ps = f"{GERRIT_CN}-{GERRIT_PS}"

其他排查点

  1. Python版本与库版本差异:检查Jenkins和本地的Python版本、sonarqube客户端版本是否一致,若版本差异较大,尝试升级Jenkins环境的库版本。
  2. 字符编码问题:极端情况下可能存在环境编码差异,但从日志看请求参数显示正常,优先级低于隐形字符排查。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 05:45:07