我使用并发期货从网页中抓取h1列表,并将它们附加到一个名为archive_h1_list的列表中。问题是,一旦并发期货遇到异常,它就会停止追加列表。
当我在下面打印结果列表时,它在第一个异常之后停止。['Example Domain', 'Example Domain', 'Exception Error!']
在遇到异常后,它永远不会继续处理列表中的最后一个https://www.example.com h1。
import concurrent.futures
from urllib.request import urlopen
from bs4 import BeautifulSoup
CONNECTIONS = 8
archive_url_list = ["https://www.example.com", "https://www.example.com", "sdfihaslkhasd", "https://www.example.com"]
archive_h1_list = []
def get_archive_h1(h1_url):
html = urlopen(h1_url)
bsh = BeautifulSoup(html.read(), 'lxml')
return bsh.h1.text.strip()
def concurrent_calls():
with concurrent.futures.ThreadPoolExecutor(max_workers=CONNECTIONS) as executor:
f1 = executor.map(get_archive_h1, archive_url_list)
try:
for future in f1:
archive_h1_list.append(future)
except Exception:
archive_h1_list.append("Exception Error!")
pass
期望的输出应该是:
['Example Domain', 'Example Domain', 'Exception Error!', 'Example Domain']
这是因为您的for
循环在try
内部,当您捕获异常时,try
块被挂起,except
块正在执行,因此您的for
循环被中断。
try
块,但是根据Executor.map
的文档:
如果函数调用引发异常,则在从迭代器中检索其值时将引发该异常。
这使得异常处理在函数之外非常糟糕。
所以第一个解决方案是捕获get_archive_h1
中的异常:
def get_archive_h1(h1_url):
try:
html = urlopen(h1_url)
bsh = BeautifulSoup(html.read(), 'lxml')
return bsh.h1.text.strip()
except Exception:
return "Exception Error!"
def concurrent_calls():
with concurrent.futures.ThreadPoolExecutor(max_workers=CONNECTIONS) as executor:
f1 = executor.map(get_archive_h1, archive_url_list)
for future in f1:
archive_h1_list.append(future)
另一种解决方案是使用不同的执行者方法,这样您可以更好地控制未来的分辨率,即Executor.submit
:
def concurrent_calls():
with concurrent.futures.ThreadPoolExecutor(max_workers=CONNECTIONS) as executor:
futures = [executor.submit(get_archive_h1, url) for url in archive_url_list]
for future in futures:
try:
archive_h1_list.append(future.result())
except Exception:
archive_h1_list.append("Exception Error!")
pass