Python 函数长时间运行不退出,线程池任务死锁等问题

import threadpool
import threading
import time


class FuncTTLMonitorDecorator(object):
    class _ResultThread(threading.Thread):
        def __init__(self, target, *args, **kwargs):
            super().__init__(daemon=True)
            self.func = target
            self.args = args
            self.kwargs = kwargs
            self.result = None

        def run(self):
            self.result = self.func(*self.args, **self.kwargs)

        def get_result(self):
            try:
                return self.result
            except Exception as e:
                return None

    def __init__(self, ttl, result_parse_func=None):
        self.ttl = int(ttl)
        self.result_parse_func = result_parse_func

    def run(self, func, *args, **kwargs) -> dict:
        """
        :param func:
        :param args:
        :param kwargs:
        :return: 参数原样返回
        """
        result = {
            'has_ttl': True,
            'ttl': self.ttl,
            'success': False,
            'error': f'The function {func.__name__}(...) timeout({self.ttl} seconds)',
            'args': args,
            'kwargs': kwargs,
            'data': None
        }
        _t = self._ResultThread(func, *args, **kwargs)
        for i in range(self.ttl):
            time.sleep(1)
            if not _t.get_result():
                continue
            result.update(success=True, error='', data=_t.get_result())
            break
        if self.result_parse_func:
            return self.result_parse_func(result)
        return result

    def __call__(self, func):
        def wrapper(*args, **kwargs):
            return self.run(func, *args, **kwargs)

        return wrapper


def general_login(args_dict, times=1):
    device = args_dict.get('device')
    try:
        while True:
            time.sleep(1)
    except Exception as e:
        device.update(error=str(e), success=False)
    return device


def ttl_result_parse(result):
    if not result.get('has_ttl'):
        return result
    if result.get('success'):
        data = result.get('data')
    else:
        data = result.get('args')[0].get('device')
        data.update(success=False, error=result.get('error'))
    return data


if __name__ == '__main__':
    pool = threadpool.ThreadPool(2)
    args_list = [
        {'device': {'ip': '10.100.235.9', 'brand': 'Aruba', 'model': '7210', 'device_type': 'aruba_os'},
         'commands': ['show running-config']
         },
        {
            'device': {'ip': '10.100.235.10', 'brand': 'Aruba', 'model': '7210', 'device_type': 'aruba_os'},
            'commands': ['show running-config']
        },
        {
            'device': {'ip': '10.100.235.1', 'brand': 'Aruba', 'model': '7210', 'device_type': 'aruba_os'},
            'commands': ['show running-config']
        }
    ]
    results = []
    tasks = threadpool.makeRequests(
        callable_=FuncTTLMonitorDecorator(ttl=3, result_parse_func=ttl_result_parse)(general_login),
        args_list=args_list,
        callback=lambda req, res: results.append(res)
    )
    [pool.putRequest(task) for task in tasks]
    pool.wait()
    import json

    print(json.dumps(results, indent=4))
 

 

output: [
    {
        "ip": "10.100.235.9",
        "brand": "Aruba",
        "model": "7210",
        "device_type": "aruba_os",
        "success": false,
        "error": "The function general_login(...) timeout(3 seconds)"
    },
    {
        "ip": "10.100.235.10",
        "brand": "Aruba",
        "model": "7210",
        "device_type": "aruba_os",
        "success": false,
        "error": "The function general_login(...) timeout(3 seconds)"
    },
    {
        "ip": "10.100.235.1",
        "brand": "Aruba",
        "model": "7210",
        "device_type": "aruba_os",
        "success": false,
        "error": "The function general_login(...) timeout(3 seconds)"
    }
]

 

posted @ 2021-03-05 11:34  士为知己  阅读(407)  评论(0)    收藏  举报