{"record":{"id":"1c35e9b73b869b8c","repo":"ZhuLinsen/daily_stock_analysis","slug":"pytdx-1c35e9","errorCode":null,"errorMessage":"Pytdx 无法连接任何服务器","messagePattern":"Pytdx 无法连接任何服务器","errorType":"exception","errorClass":"DataFetchError","httpStatus":null,"severity":"error","filePath":"data_provider/pytdx_fetcher.py","lineNumber":228,"sourceCode":"        try:\n            # 尝试连接服务器（自动选择最优）\n            for i in range(len(self._hosts)):\n                host_idx = (self._current_host_idx + i) % len(self._hosts)\n                host, port = self._hosts[host_idx]\n                \n                try:\n                    if api.connect(host, port, time_out=5):\n                        connected = True\n                        self._current_host_idx = host_idx\n                        logger.debug(f\"Pytdx 连接成功: {host}:{port}\")\n                        break\n                except Exception as e:\n                    logger.debug(f\"Pytdx 连接 {host}:{port} 失败: {e}\")\n                    continue\n            \n            if not connected:\n                self._mark_connection_cooldown(\"Pytdx 无法连接任何服务器\")\n                raise DataFetchError(\"Pytdx 无法连接任何服务器\")\n            \n            yield api\n            \n        finally:\n            # 确保断开连接\n            try:\n                api.disconnect()\n                logger.debug(\"Pytdx 连接已断开\")\n            except Exception as e:\n                logger.warning(f\"Pytdx 断开连接时出错: {e}\")\n    \n    def _get_market_code(self, stock_code: str) -> Tuple[int, str]:\n        \"\"\"\n        根据股票代码判断市场\n        \n        Pytdx 市场代码：\n        - 0: 深圳\n        - 1: 上海","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/ZhuLinsen/daily_stock_analysis/blob/5159bd72e8373d215492dff122acc9d389e219c9/data_provider/pytdx_fetcher.py#L210-L246","documentation":"DataFetchError raised after _pytdx_session() iterates every configured TDX host and none of api.connect(host, port, time_out=5) succeeds. The fetcher then marks a connection cooldown (see error 162) and re-raises, so subsequent calls fail fast for a while.","triggerScenarios":"get_security_bars / realtime quote flows when all hosts in self._hosts are unreachable or refuse connections within the 5s timeout: server outage, blocked egress, wrong host list, or DNS resolution issues.","commonSituations":"Corporate firewall blocking the TDX TCP ports; the hardcoded/public TDX server IP list gone stale; transient ISP-level outage in mainland-China network paths; container with no outbound internet.","solutions":["Verify outbound connectivity to a known TDX host (e.g. nc  <host> 7709) from the runtime host.","Catch DataFetchError at the manager level and fall back to Akshare/Tushare for A-share daily data; the cooldown means retries against pytdx will not help immediately.","Refresh the host list in PytdxFetcher configuration if the public TDX servers have changed."],"exampleFix":"# before\ntry:\n    df = pytdx_fetcher.get_stock_data(\"600519\", start, end)\nexcept DataFetchError as e:\n    raise  # every request fails for the cooldown window\n\n# after\ntry:\n    df = pytdx_fetcher.get_stock_data(\"600519\", start, end)\nexcept DataFetchError as e:\n    logger.warning(f\"pytdx failed, falling back: {e}\")\n    df = akshare_fetcher.get_stock_data(\"600519\", start, end)","handlingStrategy":"fallback","validationCode":"import socket\n\ndef tdx_host_reachable(host: str, port: int = 7709, timeout: float = 3.0) -> bool:\n    try:\n        with socket.create_connection((host, port), timeout=timeout):\n            return True\n    except OSError:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    df = pytdx_fetcher.get_stock_data(code, start, end)\nexcept DataFetchError as e:\n    if \"无法连接任何服务器\" in str(e):\n        df = akshare_fetcher.get_stock_data(code, start, end)  # cooldown already started; go elsewhere\n    else:\n        raise","preventionTips":["Verify outbound TCP access to TDX hosts from the runtime network before relying on pytdx.","Keep the host list current; public TDX IPs change over time.","Never retry-loop against pytdx right after this error — the cooldown will reject fast anyway."],"tags":["pytdx","connection-failure","network","fallback"],"backgroundTag":null,"analyzedSha":"5159bd72e8373d215492dff122acc9d389e219c9","analyzedAt":"2026-08-15T01:59:36.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}