I tried using a library (common thread) that makes the Python threading package easier to use. https://pypi.org/project/commonthread/ It's more accurate to try using it or to make it.
How to install the commonthread package
pip install -U commonthread
01.py
from commonthread import *
# source https://techacademy.jp/magazine/28155
def fibonacci_worker(th: WorkerThread, n: int):
if n <= 2:
return 1
else:
return fibonacci_worker(th, n - 2) + fibonacci_worker(th, n - 1)
thread = WorkerThread(fibonacci_worker, 36)
thread.name = 'tfib'
thread.start()
success = thread.join(timeout=0.5)
print('success={}'.format(success))
success = thread.join()
print('success={}'.format(success))
print('result={}'.format(thread.result))
print('elapsed={}'.format(thread.elapsed))
print(thread)
01.py execution result
success=False
success=True
result=14930352
elapsed=3.688599109649658
WorkerThread(name=tfib, result=14930352, elapsed=3.688599109649658, args=(36,), kwargs={}, params={})
thread = WorkerThread (fibonacci_worker, 36)
, the first argument of the WorkerThread constructor is the name of the worker function. The second and subsequent arguments are the arguments passed to the worker function. You can pass as many as you like, as long as they match the number of worker function arguments.def fibonacci_worker (th: WorkerThread, n: int)
. You need to receive this argument, but you don't have to use it.thread.join ()
, I print thread.result
and thread.elapsed
. The value returned by the worker function fibonacci_worker is automatically stored in the result member of the WorkerThread object. Also, the elapsed time taken to execute the worker function fibonacci_worker is stored in the elapsed member.print (thread)
. (For debugging)Sometimes I want to return a return value from a worker function, so it's optimized for that purpose.
02.py
from commonthread import *
# source https://techacademy.jp/magazine/28155
class FibonacciThread(CommonThread):
def entry(self, n: int):
if n <= 2:
return 1
else:
return self.entry(n - 2) + self.entry(n - 1)
thread = FibonacciThread(36)
thread.name = 'tfib'
thread.start()
thread.join()
print('result={}'.format(thread.result))
print('elapsed={}'.format(thread.elapsed))
print(thread)
02.py execution result
result=14930352
elapsed=4.399198055267334
FibonacciThread(name=tfib, result=14930352, elapsed=4.399198055267334, args=(36,), kwargs={}, params={})
class FibonacciThread (CommonThread)
, inherit from the CommonThread class.instead of
run (self). This thread that calculates the Fibonacci number takes only one integer argument, so it is
def entry (self, n: int)`. You can have an entry method with any number of arguments without having to mess with the constructor of a class that inherits from CommonThread. If it's a simple process, you don't have to bother to create a constructor definition, which is useful.03.py
from commonthread import *
class AddThread(CommonThread):
def __init__(self, x: int, y: int):
CommonThread.__init__(self)
self.x = x
self.y = y
def entry(self):
time.sleep(2.0)
return self.x + self.y
thread = AddThread(11, 22)
thread.start()
thread.join()
print('result={}'.format(thread.result))
print('elapsed={}'.format(thread.elapsed))
print(thread)
03.py execution result
result=33
elapsed=2.0015878677368164
AddThread(name=Thread-1, result=33, elapsed=2.0015878677368164, args=(), kwargs={}, params={})
class AddThread (CommonThread)
, the constructor is defined as def __init__ (self, x: int, y: int)
to accept the arguments x and y. Thus, when defining __init__
in a child class of CommonThread, you must writeCommonThread .__ init__ (self)
as its first execution line. This is like magic.def entry (self)
, and arguments other than the thread object itself are not accepted. Therefore, store the arguments in the members of self.x and slef.y in the constructor.04.py
from commonthread import *
lg = CommonThreadLogger()
lg.setup_basic()
class ShortThread(CommonThread):
def entry(self, duration):
lg.debug('start')
time.sleep(duration)
lg.debug('end')
return 'finished'
class LongThread(CommonThread):
def entry(self, duration):
lg.debug('start')
time.sleep(duration)
lg.debug('end')
return 'finished'
lg.debug('start')
sth1 = ShortThread(1.0); sth1.name = 'sth1'
sth2 = ShortThread(1.5); sth2.name = 'sth2'
lth1 = LongThread(5.0); lth1.name = 'lth1'
lth2 = LongThread(6.0); lth2.name = 'lth2'
sth1.start()
sth2.start()
lth1.start()
lth2.start()
lg.debug(CommonThread.list_alive())
CommonThread.join_all(type=ShortThread)
lg.debug(CommonThread.list_alive())
CommonThread.join_all()
lg.debug(CommonThread.list_alive())
04.py execution result
MainThread: start
sth1: start
sth2: start
lth1: start
lth2: start
MainThread: [ShortThread(name=sth1, result=None, elapsed=0.0, args=(1.0,), kwargs={}, params={}), ShortThread(name=sth2, result=None, elapsed=0.0, args=(1.5,), kwargs={}, params={}), LongThread(name=lth1, result=None, elapsed=0.0, args=(5.0,), kwargs={}, params={}), LongThread(name=lth2, result=None, elapsed=0.0, args=(6.0,), kwargs={}, params={})]
sth1: end
sth2: end
MainThread: [LongThread(name=lth1, result=None, elapsed=0.0, args=(5.0,), kwargs={}, params={}), LongThread(name=lth2, result=None, elapsed=0.0, args=(6.0,), kwargs={}, params={})]
lth1: end
lth2: end
MainThread: []
lg.setup_basic ()
after setting lg = CommonThreadLogger ()
. Comment out the line lg.setup_basic ()
when you no longer need to debug.lg.debug (~)
after executing lg.setup_basic ()
, a log with "thread name:" at the beginning of the message will be output as a standard error.CommonThread.join_all (type = ShortThread)
joins all instances of ShortThread and waits for them to finish.CommonThread.join_all ()
joins all instances of CommonThread (including LongThread) and waits for them to finish.CommonThread.list_alive ()
returns a list of all active (not finished) CommonThread objects.CommonThread.list_alive (type = ShortThread)
returns a list of all active (not finished) ShortThread objects.CommonThread.are_alive ()
to see if there are any remaining Active in CommonThread. If you specify CommonThread.are_alive (type = ShortThread)
, you can check only ShortThread.The features that could not be introduced this time are:
Recommended Posts