代码示例结合了多个Python编程概念和技术,包括装饰器、并发执行、异常处理和重试机制。
代码
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor # 多线程 多进程
import functools
import time
from retrying import retry
import random
def timer(func):
"""装饰器,用于测量函数执行时间"""
@functools.wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time() # 记录开始时间
result = func(*args, **kwargs) # 执行函数
end_time = time.time() # 记录结束时间
print(f"{func.__name__} ran in {end_time - start_time:.4f} seconds") # 打印运行时间
return result
return wrapper
@retry(stop_max_attempt_number=3, wait_random_min=1000, wait_random_max=3000)
def deal(x):
time.sleep(2)
number = random.randint(1, 10)
if number % 3 == 0:
print("发生错误", x)
raise Exception(f"手动触发的错误")
return x
@timer
def main():
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
with ThreadPoolExecutor() as executor:
# 使用map函数将任务分配到各个线程中
results = executor.map(deal, data)
# 迭代结果
for result in results:
try:
print(result) # 这里会打印函数的返回值或者抛出异常
except Exception as e:
print(f"Error occurred: {e}")
if __name__ == '__main__':
main()
知识点:
装饰器(Decorator):
timer
函数是一个装饰器,用于测量被装饰函数的执行时间。- 使用
functools.wraps
来保持原函数的名称和文档字符串。 - 装饰器记录函数开始和结束的时间,并计算运行时长。
并发编程(Concurrency):
- 使用
ThreadPoolExecutor
来创建一个线程池,用于并发执行任务。 executor.map
方法将deal
函数应用于data
列表中的每个元素。这些调用是并发执行的。
- 使用
异常处理:
- 在
main
函数中的循环内部,使用try-except
块来捕捉deal
函数抛出的任何异常。 - 如果在
deal
函数执行过程中发生异常,则打印一个错误消息。
- 在
重试机制(Retry Mechanism):
deal
函数使用retry
装饰器,它会在函数抛出异常时自动重试。- 重试参数(最大尝试次数、重试等待的最小和最大时间)在装饰器中设定。
随机数生成:
- 在
deal
函数中使用random.randint
生成一个随机整数。 - 根据这个随机数的值来决定是否抛出异常。
- 在
休眠(Sleep):
- 在
deal
函数中使用time.sleep
来模拟耗时操作。
- 在
这个代码示例是一个很好的实践,展示了如何在Python中结合使用装饰器、并发、异常处理和重试机制。这样的结构在处理需要同时管理时间效率和错误处理的复杂任务时非常有用。