类内的Python线程 [英] Python Threading inside a class
问题描述
我最近开始使用python的线程模块.经过一番尝试和错误之后,我设法使用大多数教程中给出的以下示例代码来使基本线程正常工作.
I recently started with python's threading module. After some trial and error I managed to get basic threading working using the following sample code given in most tutorials.
class SomeThread(threading.Thread):
def __init__(self, count):
threading.Thread.__init__(self)
def run(self):
print "Do something"
我的问题是:我有一个包含类变量的类和一个要在单独的线程中运行的函数.但是,该函数使用类变量,并且还会写入类变量.像这样:
My problem is: I have a Class that has class variables and a function that I want to be run in a separate thread. However the function uses class variables and also writes to class variables. Like so:
class MyClass:
somevar = 'someval'
def func_to_be_threaded(self):
# Uses other class functions
# Do something with class variables
因此,我实际上如何将线程类放入MyClass中.这样,如果调用MyClass().func_to_threaded(),它将在线程中运行.
So how would I essentially 'put the thread class in MyClass'. So that if MyClass().func_to_threaded() is called it would run in a thread.
推荐答案
如果我理解正确,那么您想在单独的线程中运行函数吗?有几种方法可以做到这一点.但基本上,您可以像下面这样包装函数:
If I understand correctly you want to run a function in a separate thread? There are several ways to do that. But basically you wrap your function like this:
class MyClass:
somevar = 'someval'
def _func_to_be_threaded(self):
# main body
def func_to_be_threaded(self):
threading.Thread(target=self._func_to_be_threaded).start()
可以用装饰器将其缩短:
It can be shortened with a decorator:
def threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs).start()
return wrapper
class MyClass:
somevar = 'someval'
@threaded
def func_to_be_threaded(self):
# main body
编辑:带有手柄的更新版本:
Edit Updated version with a handle:
def threaded(fn):
def wrapper(*args, **kwargs):
thread = threading.Thread(target=fn, args=args, kwargs=kwargs)
thread.start()
return thread
return wrapper
class MyClass:
somevar = 'someval'
@threaded
def func_to_be_threaded(self):
print 'xyz'
可以如下使用:
>>> my_obj = MyClass()
>>> handle = my_obj.func_to_be_threaded()
>>> handle.join()
现在,如果您希望从函数中返回一个值,则可以进一步扩展它.考虑一下:
Now it is possible to extend it even more if you wish to return a value from the function. Consider this:
from threading import Thread
from concurrent.futures import Future
def call_with_future(fn, future, args, kwargs):
try:
result = fn(*args, **kwargs)
future.set_result(result)
except Exception as exc:
future.set_exception(exc)
def threaded(fn):
def wrapper(*args, **kwargs):
future = Future()
Thread(target=call_with_future, args=(fn, future, args, kwargs)).start()
return future
return wrapper
class MyClass:
@threaded
def get_my_value(self):
return 1
>>> my_obj = MyClass()
>>> fut = my_obj.get_my_value() # this will run in a separate thread
>>> fut.result() # will block until result is computed
1
如果您没有 concurrent.futures.Future类(例如,因为您使用Python2.7或更旧版本),则可以使用此简化的实现:
If you don't have concurrent.futures.Future class (because for example you are using Python2.7 or older) then you can use this simplified implementation:
from threading import Event
class Future(object):
def __init__(self):
self._ev = Event()
def set_result(self, result):
self._result = result
self._ev.set()
def set_exception(self, exc):
self._exc = exc
self._ev.set()
def result(self):
self._ev.wait()
if hasattr(self, '_exc'):
raise self._exc
return self._result
我建议您仔细阅读 concurrent.futures 模块,因为它有很多简洁的工具.例如,应将Thread
类替换为ThreadPoolExecutor
实例以限制并发性(例如,您不想向10k线程发送垃圾邮件).同样,使用ThreadPoolExecutor
时,代码甚至更简单(并且更不容易出错):
I advice reading through concurrent.futures module since it has a lot of neat tools. For example Thread
class should be replaced with a ThreadPoolExecutor
instance to limit concurrency (e.g. you don't want to spam 10k threads). Also with ThreadPoolExecutor
the code is even simplier (and less error prone):
from concurrent.futures import ThreadPoolExecutor
tp = ThreadPoolExecutor(10) # max 10 threads
def threaded(fn):
def wrapper(*args, **kwargs):
return tp.submit(fn, *args, **kwargs) # returns Future object
return wrapper
请记住,在完成所有并行工作之后,您必须tp.shutdown()
.
Just remember you have to tp.shutdown()
after you're done with all parallel work.
这篇关于类内的Python线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!