面试题答案
一键面试add_done_callback方法
- 作用:为Future对象添加一个回调函数,当Future对象代表的异步操作完成(无论是正常完成还是由于异常而结束)时,这个回调函数会被调用。
- 使用场景:当你需要在异步操作完成后执行一些后续任务,但不希望阻塞主线程等待操作结果时,可以使用该方法。例如,在异步获取网页数据后,将数据写入文件或进行数据解析等操作。
- 示例代码:
import concurrent.futures
import time
def task():
time.sleep(2)
return 42
def callback(future):
result = future.result()
print(f"任务完成,结果是: {result}")
with concurrent.futures.ThreadPoolExecutor() as executor:
future = executor.submit(task)
future.add_done_callback(callback)
result方法
- 作用:获取Future对象代表的异步操作的结果。如果异步操作还未完成,调用此方法会阻塞当前线程,直到操作完成。如果操作引发了异常,
result()
会重新抛出该异常。 - 使用场景:当你需要在主线程中获取异步操作的结果并继续进行依赖于该结果的后续计算时,使用该方法。例如,异步计算两个数的和,然后在主线程中使用这个和进行其他数学运算。
- 示例代码:
import concurrent.futures
import time
def task():
time.sleep(2)
return 42
with concurrent.futures.ThreadPoolExecutor() as executor:
future = executor.submit(task)
try:
result = future.result()
print(f"获取到的结果: {result}")
except Exception as e:
print(f"发生异常: {e}")
cancel方法
- 作用:尝试取消Future对象代表的异步操作。如果操作尚未开始执行,将会被成功取消,
cancel()
方法返回True
;如果操作已经开始执行,取消操作可能失败,cancel()
方法返回False
。 - 使用场景:当你发现某个异步任务不再需要执行,例如用户取消了某个操作,或者系统资源不足需要清理任务队列时,可以使用该方法尝试取消任务。
- 示例代码:
import concurrent.futures
import time
def task():
time.sleep(5)
return 42
with concurrent.futures.ThreadPoolExecutor() as executor:
future = executor.submit(task)
time.sleep(1)
cancelled = future.cancel()
if cancelled:
print("任务已成功取消")
else:
print("任务已开始执行,无法取消")
处理Future对象可能出现的异常情况
- 在
result
方法中捕获异常:如上述result
方法示例代码,当异步操作中引发异常时,result()
会重新抛出该异常,所以可以在调用result()
的地方使用try - except
语句捕获异常。 - 在回调函数中处理异常:在
add_done_callback
添加的回调函数中,可以通过future.exception()
方法获取异步操作中引发的异常(如果有)。例如:
import concurrent.futures
import time
def task():
raise ValueError("自定义异常")
def callback(future):
exception = future.exception()
if exception:
print(f"回调函数中捕获到异常: {exception}")
else:
result = future.result()
print(f"任务完成,结果是: {result}")
with concurrent.futures.ThreadPoolExecutor() as executor:
future = executor.submit(task)
future.add_done_callback(callback)
这样可以在异步操作完成后,无论是正常完成还是因异常结束,都能对结果或异常进行适当处理。