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

Python脚本调用REST API首次成功后每60秒崩溃求助排查

定时调用REST API反复触发JSON解析错误的问题排查

问题现象

现有一个每60秒调用REST API的Python脚本,首次请求可成功,但后续每次请求都会触发错误处理逻辑,报错信息为Expecting value: line 1 column 1 (char 0)。脚本及输出如下:

原脚本

import json
import time
from datetime import datetime, timedelta
import http.client

payload = ""  # 省略实际内容
headers = {}  # 省略实际内容

def get_conn():
    try:
        ms = datetime.now() - timedelta(days=xxx)
        current_time = time.mktime(ms.timetuple())
        ms = datetime.now()
        current_time2 = time.mktime(ms.timetuple())
        api_Url = "xxxxxx".format(int(xxxx), int(xxxx))
        conn = http.client.HTTPSConnection("xxxxx")
        conn.request("GET", api_Url, payload, headers)
        print('Getting response...')
        res = conn.getresponse()
        data = res.read()
        data = data.decode("utf-8")
        data = json.loads(data)
        return data
    except Exception as e:
        handle_crash(e)

def handle_crash(e):
    print('Restarting in 60 seconds ' + str(e))
    time.sleep(60)  # Restarts the script after 60 seconds
    start()

def start():
    while True:
        data = get_conn()
        time.sleep(60)

start()

脚本输出

Getting response...
Restarting in 60 seconds Expecting value: line 1 column 1 (char 0)
Getting response...
Restarting in 60 seconds Expecting value: line 1 column 1 (char 0)
Getting response...
Restarting in 60 seconds Expecting value: line 1 column 1 (char 0)

问题原因分析

  1. JSON解析失败的直接原因:Expecting value: line 1 column 1错误表明json.loads()接收到的是空字符串或非JSON格式内容。这意味着后续请求中,API返回的响应不是有效的JSON,甚至没有返回内容。

  2. 潜在的脚本缺陷:

    • 未检查API响应状态码:首次请求成功后,后续请求可能因限流(429)、服务器错误(500)或认证失效,返回错误页面/空内容,却被直接尝试解析为JSON。
    • 未正确关闭HTTP连接:http.client.HTTPSConnection未主动关闭,可能导致连接复用失效,服务器端关闭闲置连接后,后续请求返回空响应。
    • 错误处理逻辑递归调用:handle_crash()中直接调用start()会创建嵌套的while True循环,引发逻辑混乱,甚至栈溢出风险。

解决方案

优化后的脚本

import json
import time
from datetime import datetime, timedelta
import http.client

payload = ""  # 替换为实际请求体
headers = {}  # 替换为实际请求头(如认证、Content-Type等)

def get_conn():
    # 时间参数计算
    ms_past = datetime.now() - timedelta(days=xxx)
    current_time = int(time.mktime(ms_past.timetuple()))
    current_time2 = int(time.mktime(datetime.now().timetuple()))
    
    api_url = "xxxxxx".format(current_time, current_time2)  # 替换为实际API路径模板
    conn = http.client.HTTPSConnection("xxxxx")  # 替换为实际API域名
    
    try:
        conn.request("GET", api_url, payload, headers)
        print('Getting response...')
        res = conn.getresponse()
        
        # 先检查响应状态码
        if res.status not in (200, 201):
            error_content = res.read().decode("utf-8")
            raise Exception(f"API请求失败,状态码: {res.status},响应内容: {error_content}")
        
        # 读取并解析响应
        data = res.read().decode("utf-8")
        if not data:
            raise Exception("API返回空响应")
        
        return json.loads(data)
    finally:
        # 确保连接无论成功失败都关闭
        conn.close()

def start():
    while True:
        try:
            data = get_conn()
            # 此处添加对返回数据的处理逻辑
            print(f"成功获取数据: {data}")
            time.sleep(60)
        except Exception as e:
            print(f'请求出错: {str(e)},60秒后重试...')
            time.sleep(60)

start()

关键优化点

  • 增加响应状态码校验:先判断API返回是否成功,避免无效内容进入JSON解析步骤。
  • 强制关闭HTTP连接:使用finally块确保每次请求后关闭连接,避免连接复用问题。
  • 重构错误处理逻辑:将重试逻辑放在start()的主循环中,避免递归调用导致的嵌套循环问题。

额外排查建议

  • 在调试阶段,打印完整的API响应内容,确认后续请求失败时的具体返回。
  • 检查API的调用频率限制,确认是否超过阈值导致限流。
  • 验证请求头中的认证信息(如Token)是否有效,是否存在过期或失效情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 15:05:33