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

如何修复Python中RecursionError:递归深度超出限制的问题?

XML文本翻译脚本错误修复与优化

我正在编写一个Python脚本,功能为读取XML文件、将部分变量替换为占位符、使用Google Translate API翻译文本、恢复变量后写入另一个XML文件。但运行脚本时出现如下错误:

Traceback (most recent call last):
File "C:\Users\lazar\AppData\Local\Programs\Python\Python311\Lib\xml\etree\ElementTree.py", line 757, in _get_writer
write = file_or_filename.write
^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'write'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "\translate.py", line 48, in _serialize_xml
return ET._serialize_xml(write, elem, qnames, namespaces, short_empty_elements=short_empty_elements)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "\translate.py", line 48, in _serialize_xml
return ET._serialize_xml(write, elem, qnames, namespaces, short_empty_elements=short_empty_elements)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "./translate.py", line 48, in _serialize_xml
return ET._serialize_xml(write, elem, qnames, namespaces, short_empty_elements=short_empty_elements)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[Previous line repeated 997 more times]
RecursionError: maximum recursion depth exceeded

我的代码如下:

import xml.etree.ElementTree as ET
import re
from google.cloud import translate_v2 as translate
from google.oauth2 import service_account

credentials_dict = {
#keys goes here
}


credentials = service_account.Credentials.from_service_account_info(credentials_dict)

client = translate.Client(credentials=credentials)

tree = ET.parse("input.xml")
root = tree.getroot()

def replace_variables(text):
    variables = re.findall(r"\{.*?\}", text)
    for i, variable in enumerate(variables):
        text = text.replace(variable, "~" * (i + 1))
    return text, variables

def restore_variables(text, variables):
    placeholders = re.findall(r"~+", text)
    for i, placeholder in enumerate(placeholders):
        if len(variables) > i:
            text = text.replace(placeholder, variables[i])
    return text

def CDATA(text=None):
    element = ET.Element('![CDATA[')
    element.text = text
    return element

def _serialize_xml(write, elem, qnames, namespaces, *, short_empty_elements=True):
    if elem.tag == '![CDATA[':
        write("\n<%s%s]]>\n" % (elem.tag, elem.text))
        return
    return ET._serialize_xml(write, elem, qnames, namespaces, short_empty_elements=short_empty_elements)

ET._serialize_xml = _serialize_xml

new_elements = []
for i, element in enumerate(root.iter()):
    if element.text is not None:
        text = element.text.strip()
        modified_text, variables = replace_variables(text)
        translation = client.translate(modified_text, target_language="es")
        translated_text = translation["translatedText"]
        restored_text = restore_variables(translated_text, variables)
        print(text + " -> " + restored_text)

        cdata_element = CDATA(restored_text)
        new_element = element.makeelement(element.tag, element.attrib)
        new_element.append(cdata_element)
        new_elements.append(new_element)

for i, new_element in enumerate(new_elements):
    if i < len(root):
        root[i] = new_element
    else:
        root.append(new_element)
tree.write("output.xml", encoding="utf-8", xml_declaration=True)

错误原因分析

  1. 无限递归:重写ET._serialize_xml时,直接调用了已经被替换为自定义函数的ET._serialize_xml,导致每次调用都会进入自身循环,触发递归深度超限。
  2. 元素替换逻辑错误:root.iter()遍历所有XML元素(包括所有后代),但后续仅替换root的直接子元素,导致结构混乱、重复添加元素。
  3. CDATA序列化不规范:自定义的CDATA元素标签不符合ElementTree的规则,写入文件时触发AttributeError。

修复后代码

import xml.etree.ElementTree as ET
import re
from google.cloud import translate_v2 as translate
from google.oauth2 import service_account

credentials_dict = {
    # 填入你的密钥信息
}

credentials = service_account.Credentials.from_service_account_info(credentials_dict)
client = translate.Client(credentials=credentials)

# 保存原始序列化函数,避免递归调用
original_serialize_xml = ET._serialize_xml

def replace_variables(text):
    variables = re.findall(r"\{.*?\}", text)
    # 使用语义化占位符,避免翻译时被误处理
    for i, variable in enumerate(variables):
        text = text.replace(variable, f"__TRANSLATE_VAR_{i}__")
    return text, variables

def restore_variables(text, variables):
    # 精准替换对应占位符
    for i, variable in enumerate(variables):
        text = text.replace(f"__TRANSLATE_VAR_{i}__", variable)
    return text

def CDATA(text=None):
    # 用注释元素模拟CDATA,配合序列化函数转换为标准格式
    return ET.Comment(f"CDATA_MARKER:{text}")

def _serialize_xml(write, elem, qnames, namespaces, *, short_empty_elements=True):
    # 处理自定义CDATA注释
    if isinstance(elem, ET.Comment) and elem.text.startswith("CDATA_MARKER:"):
        cdata_content = elem.text.split("CDATA_MARKER:", 1)[1]
        write(f"\n<![CDATA[{cdata_content}]]>\n")
        return
    # 调用原始函数处理其他元素
    original_serialize_xml(write, elem, qnames, namespaces, short_empty_elements=short_empty_elements)

# 替换全局序列化函数
ET._serialize_xml = _serialize_xml

tree = ET.parse("input.xml")
root = tree.getroot()

# 直接遍历修改原元素,避免结构混乱
for element in root.iter():
    if element.text and element.text.strip():
        raw_text = element.text.strip()
        modified_text, variables = replace_variables(raw_text)
        
        # 调用翻译API
        translation_result = client.translate(modified_text, target_language="es")
        translated_text = translation_result["translatedText"]
        
        # 恢复变量
        final_text = restore_variables(translated_text, variables)
        print(f"{raw_text} -> {final_text}")
        
        # 清空原元素内容,添加CDATA
        element.clear()
        element.append(CDATA(final_text))

# 写入输出文件
tree.write("output.xml", encoding="utf-8", xml_declaration=True)

关键修复点

  • 解决递归问题:提前保存原始序列化函数,自定义函数中调用原始函数而非自身,彻底终止无限递归。
  • 优化占位符:使用__TRANSLATE_VAR_0__这类语义化占位符,避免翻译时被误译或因占位符长度变化导致匹配失败。
  • 简化元素修改:直接遍历并修改原XML元素,无需重新构建元素再替换,避免结构混乱。
  • 规范CDATA处理:用注释元素模拟CDATA,通过序列化函数转换为标准CDATA格式,解决序列化时的属性错误。

额外优化建议

  • 批量翻译:收集所有待翻译文本批量调用API,减少请求次数,提升效率。
  • 异常处理:添加try-except块捕获API调用异常(网络错误、配额不足等),避免脚本崩溃。
  • 正则增强:若变量格式复杂,调整正则表达式确保精准匹配(如处理嵌套变量、特殊字符)。

内容的提问来源于stack exchange,提问作者Lázaro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 20:35:04