python threading线程装饰器,可以获取线程结果

 根据网络资料整理,并进行了优化和测试,编写了python的thread线程装饰器,用于装饰函数

个人认为是完美版:装饰器使用方便,可以分别获取结果,也可以获取全部结果集合

如下:

from threading import Thread, currentThread
import time


class thread_wrap_class:
    '''
    函数的线程装饰器,返回thread线程实例,getResult获取结果,
    thread_wrap_class.getAllResult 获取结果集合
    '''
    Result_dict = {}
    thread_dict = {}

    class MyThread(Thread):
        def __init__(self, func, name='', *args, **kwargs):
            Thread.__init__(self)
            self.func = func
            self.name = name
            self.args = args
            self.kwargs = kwargs

        def run(self):
            print(f"{self} start with thread_wrap_class...")
            self.res = self.func(*self.args, **self.kwargs)
            thread_wrap_class.Result_dict[self.ident] = self.res

        def getResult(self):
            self.join()
            return self.res

    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        _mythr = self.MyThread(self.func, self.func.__name__, *args, **kwargs)
        _mythr.start()
        self.thread_dict[_mythr.ident] = _mythr
        return _mythr

    @classmethod
    def getAllResult(cls):
        for k, thr in cls.thread_dict.items():
            thr.join()
        return cls.Result_dict


def click(callback, *args, **kwargs):
    # print('in main func with <', callback.__name__, '>', *args, **kwargs)
    return callback(*args, **kwargs)


@thread_wrap_class
def event(s):
    time.sleep(s)
    global g_a
    g_a += s
    print(f'{currentThread()} < event > finished! {s} {g_a}')
    return 'event Result :' + str(s) + '|' + str(g_a)


g_a = 100
event(4)
a = event(5)
print('a:', a.getResult())
click(event, 3)
click(event, 6)
print('event all:', thread_wrap_class.getAllResult())

 

测试输出如下:

<MyThread(event, started 18024)> start with thread_wrap_class...

<MyThread(event, started 4636)> start with thread_wrap_class...

<MyThread(event, started 18024)> < event > finished! 4 104

<MyThread(event, started 4636)> < event > finished! 5 109

a: event Result :5|109

<MyThread(event, started 24920)> start with thread_wrap_class...

<MyThread(event, started 4012)> start with thread_wrap_class...

<MyThread(event, started 24920)> < event > finished! 3 112

<MyThread(event, started 4012)> < event > finished! 6 118

event all: {18024: 'event Result :4|104', 4636: 'event Result :5|109', 24920: 'event Result :3|112', 4012: 'event Result :6|118'}

符合预期,完成!

<think>好的,我需要帮助用户理解如何在Python中使用线程装饰器传递参数。首先,我得回忆一下Python装饰器线程的基本概念。装饰器是用来修改或增强函数行为的,而线程通常通过threading模块创建,比如Thread类或者ThreadPoolExecutor。 用户的问题是关于如何给线程装饰器传参。首先,我需要确认装饰器的作用。通常,线程装饰器的作用是将一个普通函数转换为在新线程中运行的函数。这时候,传递参数可能涉及两个方面:装饰器本身的参数和被装饰函数的参数。 接下来,我应该考虑装饰器的结构。装饰器如果带参数的话,需要三层嵌套函数。例如,一个带参数的装饰器可能像这样:@decorator(arg1, arg2),然后装饰一个函数。对于线程装饰器来说,可能的参数包括线程名称、是否守护线程等。 然后,我需要思考如何将装饰器的参数传递给线程。例如,用户可能希望装饰器接受daemon参数,来决定线程是否是守护线程。这时候,装饰器内部需要创建一个线程,并应用这些参数。 同时,被装饰的函数本身可能有参数,这些参数在调用被装饰后的函数时需要传递进去。例如,用户调用被装饰的函数时传入参数,这些参数应该传递给原始函数,并在新线程中执行。 接下来,我需要构造一个例子来说明这个过程。例如,定义一个thread_decorator,它接受daemon参数,然后装饰一个函数。当调用被装饰的函数时,传递的参数会被正确传给原始函数,并在新线程中运行。 需要注意的是,装饰器的正确结构,外层处理装饰器参数,中间层处理函数,内层处理函数的执行和线程的启动。另外,可能需要使用functools.wraps来保留原函数的元数据。 还要考虑错误处理,比如如果装饰器参数不正确,或者被装饰函数的参数传递有误,但用户的问题可能更关注基本用法,所以先给出基础示例,再逐步扩展。 可能的例子包括: 1. 不带参数的线程装饰器,直接启动线程执行函数。 2. 带参数的装饰器,允许设置daemon等线程属性。 3. 处理被装饰函数的多参数情况,使用*args和**kwargs传递。 最后,需要总结关键点,强调装饰器参数和函数参数的不同传递方式,并提醒注意事项,比如线程启动的方法(可能需要显式调用start(),或者在装饰器中自动启动)。</think>在Python中使用装饰器传递参数给线程需要分两层处理:装饰器参数和线程函数参数。以下分步骤说明: --- ### 一、基础线程装饰器结构 首先创建一个不带参数的线程装饰器: ```python import threading from functools import wraps def thread_decorator(func): @wraps(func) def wrapper(*args, **kwargs): thread = threading.Thread(target=func, args=args, kwargs=kwargs) thread.start() return thread # 返回线程对象以便后续操作 return wrapper # 使用示例 @thread_decorator def my_task(a, b): print(f"线程执行: {a + b}") my_task(3, 5) # 输出:线程执行: 8 ``` --- ### 二、给装饰器本身传参 若需要向装饰器传递参数(如设置线程为守护线程): ```python def thread_decorator_with_args(daemon=False): def decorator(func): @wraps(func) def wrapper(*args, **kwargs): thread = threading.Thread( target=func, args=args, kwargs=kwargs, daemon=daemon # 接收装饰器参数 ) thread.start() return thread return wrapper return decorator # 使用示例 @thread_decorator_with_args(daemon=True) # 传递装饰器参数 def my_daemon_task(x): print(f"守护线程执行: {x**2}") my_daemon_task(4) # 输出:守护线程执行: 16 ``` --- ### 三、同时传递装饰器参数和函数参数 调用被装饰函数时,参数会自动传递给线程函数: ```python @thread_decorator_with_args(daemon=True) def complex_task(name, count): for i in range(count): print(f"{name}: {i}") # 传递函数参数 complex_task("Worker", 3) # 输出: # Worker: 0 # Worker: 1 # Worker: 2 ``` --- ### 关键点总结 1. **装饰器参数传递** 通过三层嵌套结构:外层接收装饰器参数 → 中间层接收函数 → 内层执行线程逻辑。 2. **线程函数参数传递** 使用`*args`和`**kwargs`捕获所有位置参数和关键字参数,通过`threading.Thread`的`args`和`kwargs`参数传递。 3. **线程控制** 返回线程对象后,可通过`.join()`等待线程完成: ```python t = complex_task("Worker", 3) t.join() # 等待线程结束 ``` --- ### 注意事项 - 如果线程函数有返回值,需要通过队列(`queue.Queue`)或回调函数获取结果。 - 装饰器默认自动启动线程,若需要手动控制启动时机,可移除`thread.start()`并在外部调用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值