Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

Recursion Error: Process_element / process_tag mutual recursion (infinite loop)

未关闭
#256 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

@chiliec 已经在做这个了。

开始于 2026年8月27日。

  • #274 来自 @chiliec —— 未关闭

评估

难度
3/5
预计耗时
1-2 天
新手友好度
50/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
停滞
技术栈
python
领域
tooling

调研方向

先在 markdownify/init.py 中阅读 process_element 和 process_tag,然后使用包含循环引用的 HTML 树重现 RecursionError。跟踪子元素处理如何经过这两个方法,并验证转换能够在不耗尽堆栈的情况下终止,同时正常的 HTML 转换保持不变。

由索引模型根据 Issue 内容生成。

描述

When converting HTML that contains circular parent-child references in the parsed BeautifulSoup tree (produced by certain PDF-to-HTML pipelines), process_element and process_tag recurse infinitely, crashing with a RecursionError.

Encountered when using markdownify via marker-pdf to convert PDF documents. The HTML produced by the PDF parser contained structures that caused BeautifulSoup's html.parser to create a non-tree graph where a descendant node held a reference back to an ancestor creating an unbounded call stack.

The mutual recursion introduced in 1.2.2 between process_element and process_tag has no cycle guard:

  • process_tag iterates node.children and calls process_element for each child
  • process_element calls process_tag for any Tag node
RecursionError: maximum recursion depth exceeded

File "markdownify/__init__.py", line 232, in process_element
    return self.process_tag(node, parent_tags=parent_tags)
File "markdownify/__init__.py", line 287, in process_tag
    child_strings = [
File "markdownify/__init__.py", line 288, in <listcomp>
    self.process_element(el, parent_tags=parent_tags_for_children)
File "markdownify/__init__.py", line 232, in process_element
    return self.process_tag(node, parent_tags=parent_tags)
... (repeating until stack exhausted)

Suggested fix:

Pass a visited set of node ids through the call chain to detect and break cycles:

def process_element(self, node, parent_tags=None, _visited=None):
    if isinstance(node, NavigableString):
        return self.process_text(node, parent_tags=parent_tags)
    else:
        return self.process_tag(node, parent_tags=parent_tags, _visited=_visited)

def process_tag(self, node, parent_tags=None, _visited=None):
    if parent_tags is None:
        parent_tags = set()

    # Cycle detection
    if _visited is None:
        _visited = set()
    node_id = id(node)
    if node_id in _visited:
        return ''
    _visited.add(node_id)

    # ... rest of method unchanged, but pass _visited= to process_element calls
    child_strings = [
        self.process_element(el, parent_tags=parent_tags_for_children, _visited=_visited)
        for el in children_to_convert
    ]

主要语言
Python
星标
2.3k
派生
210
PR 合并指标
30 天内没有已合并 PR

环境准备

这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

matthewwithanm/python-markdownify 的其他 Issue

查看 matthewwithanm/python-markdownify 的全部 Issue

相似的 Issue

更多 Python Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。