{"record":{"id":"676fbfc8f8688415","repo":"hsliuping/TradingAgents-CN","slug":"akshare-api","errorCode":null,"errorMessage":"AKShare API 调用超时（其他线程占用）","messagePattern":"AKShare API 调用超时（其他线程占用）","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"tradingagents/dataflows/providers/hk/improved_hk.py","lineNumber":705,"sourceCode":"\n        # 尝试从 akshare 获取实时行情\n        try:\n            # 🔥 使用互斥锁保护 AKShare API 调用（防止并发导致被封禁）\n            # 策略：\n            # 1. 尝试获取锁（最多等待 60 秒）\n            # 2. 获取锁后，先检查缓存是否已被其他线程更新\n            # 3. 如果缓存有效，直接使用；否则调用 API\n\n            thread_id = threading.current_thread().name\n            logger.info(f\"🔒 [AKShare锁-{thread_id}] 尝试获取锁...\")\n\n            # 尝试获取锁，最多等待 60 秒\n            lock_acquired = _akshare_hk_spot_lock.acquire(timeout=60)\n\n            if not lock_acquired:\n                # 超时，返回错误\n                logger.error(f\"⏰ [AKShare锁-{thread_id}] 获取锁超时（60秒），放弃\")\n                raise Exception(\"AKShare API 调用超时（其他线程占用）\")\n\n            try:\n                logger.info(f\"✅ [AKShare锁-{thread_id}] 已获取锁\")\n\n                # 获取锁后，检查缓存是否已被其他线程更新\n                now = datetime.now()\n                cache = _akshare_hk_spot_cache\n\n                if cache['data'] is not None and cache['timestamp'] is not None:\n                    elapsed = (now - cache['timestamp']).total_seconds()\n                    if elapsed <= cache['ttl']:\n                        # 缓存有效（可能是其他线程刚更新的）\n                        logger.info(f\"⚡ [AKShare缓存-{thread_id}] 使用缓存数据（{elapsed:.1f}秒前，可能由其他线程更新）\")\n                        df = cache['data']\n                    else:\n                        # 缓存过期，需要调用 API\n                        logger.info(f\"🔄 [AKShare缓存-{thread_id}] 缓存过期（{elapsed:.1f}秒前），调用 API 刷新\")\n                        df = ak.stock_hk_spot()","sourceCodeStart":687,"sourceCodeEnd":723,"githubUrl":"https://github.com/hsliuping/TradingAgents-CN/blob/74783e8817d6cf6de29867880631cc555153f36b/tradingagents/dataflows/providers/hk/improved_hk.py#L687-L723","documentation":"Raised by get_hk_stock_info_akshare when the global _akshare_hk_spot_lock could not be acquired within 60 seconds, meaning another thread is stuck inside the serialized AKShare HK spot call. AKShare HK endpoints are not thread-safe, so access is mutex-serialized per process.","triggerScenarios":"Multiple concurrent calls to get_hk_stock_info_akshare (e.g. several HK symbols in parallel) while the thread holding the lock blocks on a slow/hung AKShare HTTP request for over 60 seconds.","commonSituations":"Parallel batch fetching of many HK stocks, AKShare upstream slowness or rate limiting making one call exceed the timeout, thread pools sized larger than the lock can drain.","solutions":["Retry after a short wait — the lock is usually released once the slow call finishes","Reduce concurrency for HK AKShare calls (serialize or limit workers to 1-2)","Add per-call timeouts/retries around get_hk_stock_info_akshare","If persistent, switch the HK datasource or check AKShare network health"],"exampleFix":"# before\ninfo = get_hk_stock_info_akshare('00700')\n# after\nfor attempt in range(3):\n    try:\n        info = get_hk_stock_info_akshare('00700'); break\n    except Exception as e:\n        if '超时' not in str(e): raise\n        time.sleep(10)","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for attempt in range(3):\n    try:\n        info = get_hk_stock_info_akshare(symbol)\n        break\n    except Exception as e:\n        if 'AKShare API 调用超时' not in str(e) or attempt == 2:\n            raise\n        time.sleep(15)","preventionTips":["Serialize HK AKShare calls (one worker) since the library enforces a global lock","Add jittered retries around HK fetches","Monitor AKShare latency and switch datasource when it degrades"],"tags":["python","akshare","hong-kong-stocks","concurrency","timeout"],"backgroundTag":"lock-acquisition-timeout","analyzedSha":"74783e8817d6cf6de29867880631cc555153f36b","analyzedAt":"2026-08-28T11:39:07.729Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}