python Returning data from a threaded def
I have a bit of code that gets the title of a .MP3 file
def getTitle(fileName):
print "getTitle"
audio = MP3(fileName)
try:
开发者_如何学运维 sTitle = str(audio["TIT2"])
except KeyError:
sTitle = os.path.basename(fileName)
sTitle = replace_all(sTitle) #remove special chars
return sTitle
I would call this function with
sTitle = getTitle("SomeSong.mp3")
To solve another problem I wanted to spawn this on its own thread so I altered my call to
threadTitle = Thread(target=getTitle("SomeSong.mp3"))
threadTitle.start()
This correctly calls the function and solves my other problem, but now I can't figure out how to get the return value of sTitle from the function into Main.
I would make a new object that extends thread so that you can get anything you want out of it at any time.
from threading import Thread
class GetTitleThread(Thread):
def __init__(self, fileName):
self.sTitle = None
self.fileName = fileName
super(GetTitleThread, self).__init__()
def run(self):
print "getTitle"
audio = MP3(self.fileName)
try:
self.sTitle = str(audio["TIT2"])
except KeyError:
self.sTitle = os.path.basename(self.fileName)
self.sTitle = replace_all(self.sTitle) #remove special chars
if __name__ == '__main__':
t = GetTitleThread('SomeSong.mp3')
t.start()
t.join()
print t.sTitle
One way to do it is to use a wrapper storing the result:
def wrapper(func, args, res):
res.append(func(*args))
res = []
t = threading.Thread(
target=wrapper, args=(getTitle, ("SomeSong.mp3",), res))
t.start()
t.join()
print res[0]
This one comfortably makes any function running in a thread taking care of its return value or exception:
def threading_func(f):
"""Decorator for running a function in a thread and handling its return
value or exception"""
def start(*args, **kw):
def run():
try:
th.ret = f(*args, **kw)
except:
th.exc = sys.exc_info()
def get(timeout=None):
th.join(timeout)
if th.exc:
raise th.exc[0], th.exc[1], th.exc[2] # py2
##raise th.exc[1] #py3
return th.ret
th = threading.Thread(None, run)
th.exc = None
th.get = get
th.start()
return th
return start
Usage Examples
def f(x):
return 2.5 * x
th = threading_func(f)(4)
print("still running?:", th.is_alive())
print("result:", th.get(timeout=1.0))
@threading_func
def th_mul(a, b):
return a * b
th = th_mul("text", 2.5)
try:
print(th.get())
except TypeError:
print("exception thrown ok.")
精彩评论