Python Advanced - Threads and Threading
Python Advanced - Threads and Threading
THREADS IN PYTHON
DEFINITION OF A THREAD
Kernel threads
User-space Threads or user threads
Kernel Threads are part of the operating system, while User-space threads are not
implemented in the kernel.
In a certain way, user-space threads can be seen as an extension of the function concept of a
programming language. So a thread user-space thread is similar to a function or procedure
call. But there are differences to regular functions, especially the return behaviour.
Every process has at least one thread, i.e. the process itself. A process can start multiple
threads. The operating system executes these threads like parallel "processes". On a single
processor machine, this parallelism is achieved by thread scheduling or timeslicing.
Advantages of Threading:
Multithreaded programs can run faster on computer systems with multiple CPUs,
because theses threads can be executed truly concurrent.
https://www.python-course.eu/threads.php 1/9
4/19/2019 Python Advanced: Threads and Threading
The handling of threads is simpler than the handling of processes for an operating system.
That's why they are sometimes called light-weight process (LWP)
THREADS IN PYTHON
There are two modules which support the usage of threads in Python:
thread
and
threading
Please note: The thread module has been considered as "deprecated" for quite a long time.
Users have been encouraged to use the threading module instead. So,in Python 3 the module
"thread" is not available anymore. But that's not really true: It has been renamed to "_thread"
for backwards incompatibilities in Python3.
The module "thread" treats a thread as a function, while the module "threading" is
implemented in an object oriented way, i.e. every thread corresponds to an object.
It's possible to execute functions in a separate thread with the module Thread. To do this, we
can use the function thread.start_new_thread:
https://www.python-course.eu/threads.php 2/9
4/19/2019 Python Advanced: Threads and Threading
This method starts a new thread and return its identifier. The thread executes the function
"function" (function is a reference to a function) with the argument list args (which must be a
list or a tuple). The optional kwargs argument specifies a dictionary of keyword arguments.
When the function returns, the thread silently exits. When the function terminates with an
unhandled exception, a stack trace is printed and then the thread exits (but other threads
continue to run).
def heron(a):
"""Calculates the square root of a"""
eps = 0.0000001
old = 1
new = 1
while True:
old,new = new, (new + a/new) / 2.0
print old, new
if abs(new - old) < eps:
break
return new
start_new_thread(heron,(99,))
start_new_thread(heron,(999,))
start_new_thread(heron,(1733,))
The raw_input() in the previous example is necessary, because otherwise all the threads would
be exited, if the main program finishes. raw_input() waits until something has been typed in.
num_threads = 0
def heron(a):
global num_threads
num_threads += 1
start_new_thread(heron,(99,))
start_new_thread(heron,(999,))
start_new_thread(heron,(1733,))
start_new_thread(heron,(17334,))
https://www.python-course.eu/threads.php 3/9
4/19/2019 Python Advanced: Threads and Threading
The script above doesn't work the way we might expect it to work. What is wrong?
The problem is that the final while loop will be reached even before one of the threads could
have incremented the counter num_threads.
SOLUTION
Problems of this kind can be solved by defining critical sections with lock objects. These
sections will be treated atomically, i.e. during the execution of such a section a thread will not
be interrupted or put to sleep.
The methode thread.allocate_lock is used to create a new lock object:
lock_object = thread.allocate_lock()
The beginning of a critical section is tagged with lock_object.acquire() and the end with
lock_object.release().
The solution with locks looks like this:
https://www.python-course.eu/threads.php 4/9
4/19/2019 Python Advanced: Threads and Threading
...
lock.acquire()
num_threads -= 1
lock.release()
return new
start_new_thread(heron,(99,))
start_new_thread(heron,(999,))
start_new_thread(heron,(1733,))
THREADING MODULE
We want to introduce the threading module with an example. The Thread of the example
doesn't do a lot, essentially it just sleeps for 5 seconds and then prints out a message:
import time
from threading import Thread
def sleeper(i):
print "thread %d sleeps for 5 seconds" % i
time.sleep(5)
print "thread %d woke up" % i
for i in range(10):
t = Thread(target=sleeper, args=(i,))
t.start()
Method of operation of the threading.Thread class: The class threading.Thread has a method
start(), which can start a Thread. It triggers off the method run(), which has to be overloaded.
The join() method makes sure that the main program waits until all threads have terminated.
https://www.python-course.eu/threads.php 5/9
4/19/2019 Python Advanced: Threads and Threading
The next example shows a thread, which determines, if a number is prime or not. The Thread
is defined with the threading module:
import threading
class PrimeNumber(threading.Thread):
def __init__(self, number):
threading.Thread.__init__(self)
self.Number = number
def run(self):
counter = 2
while counter*counter < self.Number:
if self.Number % counter == 0:
print "%d is no prime number, because %d = %d * %d" % (
self.Number, self.Number, counter, self.Number / counter)
return
counter += 1
print "%d is a prime number" % self.Number
threads = []
while True:
input = long(raw_input("number: "))
if input < 1:
break
thread = PrimeNumber(input)
threads += [thread]
thread.start()
for x in threads:
x.join()
https://www.python-course.eu/threads.php 6/9
4/19/2019 Python Advanced: Threads and Threading
def run(self):
counter = 2
res = True
while counter*counter < self.Number and res:
if self.Number % counter == 0:
res = False
counter += 1
PrimeNumber.lock.acquire()
PrimeNumber.prime_numbers[self.Number] = res
PrimeNumber.lock.release()
threads = []
while True:
input = long(raw_input("number: "))
if input < 1:
break
thread = PrimeNumber(input)
threads += [thread]
thread.start()
for x in threads:
x.join()
https://www.python-course.eu/threads.php 7/9
4/19/2019 Python Advanced: Threads and Threading
"+ip,"r").
A solution without threads is highly inefficient, because the script will have to wait for every
ping.
To understand this script, we have to look at the results of a ping on a shell command line:
$ ping -q -c2 192.168.178.26
PING 192.168.178.26 (192.168.178.26) 56(84) bytes of data.
class ip_check(threading.Thread):
def __init__ (self,ip):
threading.Thread.__init__(self)
self.ip = ip
self.__successful_pings = -1
https://www.python-course.eu/threads.php 8/9
4/19/2019 Python Advanced: Threads and Threading
def run(self):
ping_out = os.popen("ping -q -c2 "+self.ip,"r")
while True:
line = ping_out.readline()
if not line: break
n_received = re.findall(received_packages,line)
if n_received:
self.__successful_pings = int(n_received[0])
def status(self):
if self.__successful_pings == 0:
return "no response"
elif self.__successful_pings == 1:
return "alive, but 50 % package loss"
elif self.__successful_pings == 2:
return "alive"
else:
return "shouldn't occur"
received_packages = re.compile(r"(\d) received")
check_results = []
for suffix in range(20,70):
ip = "192.168.178."+str(suffix)
current = ip_check(ip)
check_results.append(current)
current.start()
for el in check_results:
el.join()
print "Status from ", el.ip,"is",el.status()
© 2011 - 2018, Bernd Klein, Bodenseo; Design by Denise Mitchinson adapted for python-course.eu by
Bernd Klein
https://www.python-course.eu/threads.php 9/9