类内的Python线程

我最近开始使用python的线程模块。经过一些尝试和错误后,我使用大多数教程中给出的以下示例代码成功地实现了基本线程

类SomeThread(threading.Thread):
定义初始化(自我,计数):
threading.Thread.\uuuuu init\uuuuuu(自)
def运行(自):
打印“做点什么”

我的问题是:我有一个包含类变量的类和一个我希望在单独线程中运行的函数。但是,该函数使用类变量并写入类变量。像这样:

类MyClass:
somevar='someval'
def func to be_螺纹(自):
#使用其他类函数
#对类变量做些什么

那么我将如何本质上“将线程类放入MyClass”。因此,如果调用MyClass().func_to_threaded(),它将在线程中运行

如果我理解正确,您希望在单独的线程中运行函数吗?有几种方法可以做到这一点。但基本上你可以这样包装你的函数:

类MyClass:
somevar='someval'
def_func_to_be_螺纹(自):
#主体
def func to be_螺纹(自):
threading.Thread(target=self.\u func\u to\u be\u threaded).start()

可以使用装饰器将其缩短:

def螺纹化(fn):
def包装(*args,**kwargs):
threading.Thread(target=fn,args=args,kwargs=kwargs).start()
返回包装器
类别MyClass:
somevar=’someval’
@螺纹
def func to be_螺纹(自):
#主体


编辑带有句柄的更新版本:

def螺纹化(fn):
def包装(*args,**kwargs):
线程(target=fn,args=args,kwargs=kwargs)
thread.start()
回位螺纹
返回包装器
类别MyClass:
somevar=’someval’
@螺纹
def func to be_螺纹(自):
打印“xyz”

这可以按如下方式使用:

&gt&燃气轮机&燃气轮机;my_obj=MyClass()
&燃气轮机&燃气轮机&燃气轮机;handle=my_obj.func_to_be_threaded()
&燃气轮机&燃气轮机&燃气轮机;handle.join()

现在,如果希望从函数返回值,可以进一步扩展它。考虑这一点:

从线程导入线程
从期货进口期货
def呼叫未来(fn、未来、ARG、kwargs):
尝试:
结果=fn(*args,**kwargs)
future.set_结果(result)
除作为exc的例外情况外:
future.set_异常(exc)
def螺纹(fn):
def包装(*args,**kwargs):
future=future()
线程(target=call_和_future,args=(fn,future,args,kwargs)).start()
回归未来
返回包装器
类别MyClass:
@螺纹
def获取我的值(自我):
返回1
&燃气轮机&燃气轮机&燃气轮机;my_obj=MyClass()
&燃气轮机&燃气轮机&燃气轮机;fut=my_obj.get_my_value()#这将在单独的线程中运行
&燃气轮机&燃气轮机&燃气轮机;fut.result()#将阻塞,直到计算出结果
1.

如果您没有concurrent.futures.Future类(例如,因为您使用的是Python2.7或更早版本),则可以使用以下简化实现:

来自线程导入事件的


类未来(对象):
定义初始化(自):
self._ev=事件()
def设置结果(自身、结果):
self.\u result=结果
self._ev.set()
def set_异常(自身、exc):
自我评价.\u exc=exc
self._ev.set()
def结果(自我):
self._ev.wait()
如果hasattr(self,“\u exc”):
自我提升
返回自己的结果

我建议阅读concurrent.futures模块,因为它有很多简洁的工具。例如,应将Thread类替换为ThreadPoolExecutor实例以限制并发性(例如,您不想垃圾邮件发送10k个线程)。另外,使用ThreadPoolExecutor时,代码更加简单(且不易出错):

来自concurrent.futures导入ThreadPoolExecutor的


tp=线程池执行器(10)#最多10个线程
def螺纹(fn):
def包装(*args,**kwargs):
返回tp.submit(fn,*args,**kwargs)#返回未来对象
返回包装器

请记住,在完成所有并行工作后,必须tp.shutdown()

发表评论