【发布时间】:2021-04-25 23:10:05
【问题描述】:
我正在尝试在 python 中简单地制作我的 URL 类的独立副本,这样我就可以在不影响原始文件的情况下修改副本。
以下是我的问题代码的精简可执行版本:
from bs4 import BeautifulSoup
from copy import deepcopy
from urllib import request
url_dict = {}
class URL:
def __init__(self, url, depth, log_entry=None, soup=None):
self.url = url
self.depth = depth # Current, not total, depth level
self.log_entry = log_entry
self.soup = soup
self.indent = ' ' * (5 - self.depth)
self.log_url = 'test.com'
# Blank squad
self.parsed_list = []
def get_log_output(self):
return self.indent + self.log_url
def get_print_output(self):
if self.log_entry is not None:
return self.indent + self.log_url + ' | ' + self.log_entry
return self.indent + self.log_url
def set_soup(self):
if self.soup is None:
code = ''
try: # Read and store code for parsing
code = request.urlopen(self.url).read()
except Exception as exception:
print(str(exception))
self.soup = BeautifulSoup(code, features='lxml')
def crawl(current_url, current_depth):
current_check_link = current_url
has_crawled = current_check_link in url_dict
if current_depth > 0 and not has_crawled:
current_crawl_job = URL(current_url, current_depth)
current_crawl_job.set_soup()
url_dict[current_check_link] = deepcopy(current_crawl_job)
for link in ['http://xts.site.nfoservers.com']: # Crawl for each URL the user inputs
crawl(link, 3)
产生的异常:
Traceback (most recent call last):
File "/home/[CENSORED]/.vscode-oss/extensions/ms-python.python-2020.10.332292344/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_trace_dispatch_regular.py", line 374, in __call__
if cache_skips.get(frame_cache_key) == 1:
RecursionError: maximum recursion depth exceeded in comparison
Fatal Python error: _Py_CheckRecursiveCall: Cannot recover from stack overflow.
Python runtime state: initialized
我无法判断这个特定的无限递归发生在哪里。我已经阅读了诸如
RecursionError when python copy.deepcopy 但我什至不确定它是否适用于我的用例。如果它确实适用,那么我的大脑似乎无法理解它,因为我的印象是deepcopy() 应该只获取每个self 变量值并将其复制到新类中。如果不是这样,那么我会喜欢一些启蒙。我的搜索结果中的所有文章都类似于this,对我的情况没有太大帮助。
请注意,我不只是在寻找修改过的我的代码的 sn-p 来解决这个问题。我主要想了解这里到底发生了什么,这样我既可以现在修复它,也可以在将来避免它。
编辑:这似乎是 deepcopy 和 set_soup() 方法之间的冲突。如果我更换
url_dict[current_check_link] = deepcopy(current_crawl_job)
与
url_dict[current_check_link] = current_crawl_job
上面的 sn-p 运行没有错误。同样,如果我完全删除 current_crawl_job.set_soup(),我也不会收到任何错误。我就是不能两者兼得。
Edit2:我可以删除任何一个
try: # Read and store code for parsing
code = request.urlopen(self.url).read()
except Exception as exception:
print(str(exception))
或
self.soup = BeautifulSoup(code, features='lxml')
错误再次消失,程序正常运行。
【问题讨论】:
-
发布运行并在运行时重现错误的内容。此外,您似乎正在通过 IDE 运行此代码,可能使用调试器。如果直接通过命令行运行,是否还会出现错误?
-
@user2357112supportsMonica 是的,我直接从 CLI 运行时遇到同样的错误。而且我会开发一个可以真正快速运行的 sn-p。
-
这似乎完全是由于其他原因,可能与我的其他递归有关,因为我无法在较小的 sn-p 中重现它。我会继续努力,但似乎它可能与我已经在使用递归搜索树的事实有关。一旦我遇到功能性问题 sn-p,我将更新问题。我真的不希望人们为我调试我的整个文件,但我认为我应该在处理这个问题时至少提供一些东西。
-
您可以使用
sys.settrace()来跟踪代码中的调用并确定递归发生的位置。见Tracing a Program As It Runs。 -
添加了一个产生相同错误的工作代码 sn-p。我也会看看@martineau,谢谢。