Python 中 RuntimeError: maximum recursion depth exceeded

138 阅读2分钟

在使用 Python 编程时,遇到了一个错误 RuntimeError: maximum recursion depth exceeded。该错误发生的原因是代码中存在递归调用,导致调用堆栈深度过大,超过了 Python 解释器的最大递归深度限制。

在本文中,我将介绍如何解决此错误,并提供一个代码示例来说明解决方案。

2、解决方案

为了解决此错误,我们需要找到代码中存在递归调用的位置,并将其改为迭代实现。

在本文的代码示例中,错误发生在 updateShelfWithTabBody 函数中,该函数负责更新一个存储了歌曲详细信息的 shelf 文件。

def updateShelfWithTabBody(shelfFileName, newShelfFileName):
    """this function updates songDetails with
    html body i.e. just the part that contains lyrics and
    chords in the tab """

    # read all songDetails
    shelf = shelve.open(shelfFileName)
    listOfKeys = shelf.keys()

    # create new songDetails object
    temporaryShelfObject = SongDetails.SongDetails()

    # iterate over list of keys
    for key in listOfKeys:
        # print "name:"+shelf[key].name
        # fill details from temporaryShelfObject
        temporaryShelfObject.name = shelf[key].name
        temporaryShelfObject.tabHtmlPageContent = shelf[key].tabHtmlPageContent
        # add new detail information
        htmlPageContent = shelf[key].tabHtmlPageContent
        temporaryShelfObject.htmlBodyContent = extractDataFromDocument.fetchTabBody(htmlPageContent)
        # write SongDetails back to shelf
        writeSongDetails.writeSongDetails(temporaryShelfObject, newShelfFileName)

在该函数中,extractDataFromDocument.fetchTabBody 函数被调用来提取歌曲的正文内容。

def fetchTabBody(page_contents):
    soup = BeautifulSoup(page_contents)
    HtmlBody = ""
    try:
            #The lyrics and chords of song are contained in div with id = "cont"
            #Note: This assumtption is specific to ultimate-guitar.com
            HtmlBody = soup.html.body.find("div",{"id":"cont"})
    except:
            print "Error: ",sys.exc_info()[0]
    return HtmlBody

该函数内部使用了递归调用,导致调用堆栈深度过大,超过了 Python 解释器的最大递归深度限制。

为了解决这个问题,我们可以将该函数改为迭代实现。

def fetchTabBody(page_contents):
    soup = BeautifulSoup(page_contents)
    HtmlBody = ""
    for child in soup.html.body.find("div",{"id":"cont"}).descendants:
            if child.name in ["p","br"]:
                    HtmlBody += str(child)

    return HtmlBody

通过将 extractDataFromDocument.fetchTabBody 函数改为迭代实现,我们可以避免递归调用,从而解决 RuntimeError: maximum recursion depth exceeded 错误。

代码示例

以下是一个完整的代码示例,演示了如何解决 RuntimeError: maximum recursion depth exceeded 错误。

import shelve
import BeautifulSoup
import sys

class SongDetails:
    name = ""
    tabHtmlPageContent = ""
    genre = ""
    year = ""
    artist = ""
    chordsAndLyrics = ""
    htmlBodyContent = ""
    scale = ""
    chordsUsed = []

def updateShelfWithTabBody(shelfFileName, newShelfFileName):
    """this function updates songDetails with
    html body i.e. just the part that contains lyrics and
    chords in the tab """

    # read all songDetails
    shelf = shelve.open(shelfFileName)
    listOfKeys = shelf.keys()

    # create new songDetails object
    temporaryShelfObject = SongDetails.SongDetails()

    # iterate over list of keys
    for key in listOfKeys:
        # print "name:"+shelf[key].name
        # fill details from temporaryShelfObject
        temporaryShelfObject.name = shelf[key].name
        temporaryShelfObject.tabHtmlPageContent = shelf[key].tabHtmlPageContent
        # add new detail information
        htmlPageContent = shelf[key].tabHtmlPageContent
        temporaryShelfObject.htmlBodyContent = fetchTabBody(htmlPageContent)
        # write SongDetails back to shelf
        writeSongDetails.writeSongDetails(temporaryShelfObject, newShelfFileName)

def fetchTabBody(page_contents):
    soup = BeautifulSoup(page_contents)
    HtmlBody = ""
    for child in soup.html.body.find("div",{"id":"cont"}).descendants:
            if child.name in ["p","br"]:
                    HtmlBody += str(child)

    return HtmlBody

def writeSongDetails(songDetails, shelfFileName):
    shelf = shelve.open(shelfFileName)
    songDetails.name = str(songDetails.name).strip(' ')
    shelf[songDetails.name] = songDetails
    shelf.close()

if __name__ == "__main__":
    shelfFileName = "songDetails.shelf"
    newShelfFileName = "newSongDetails.shelf"
    updateShelfWithTabBody(shelfFileName, newShelfFileName)

在该代码示例中,我们将 extractDataFromDocument.fetchTabBody 函数改为迭代实现,避免了递归调用,从而解决了 RuntimeError: maximum recursion depth exceeded 错误。