Python Threading Operations
With Python Threading operations, applications that will take a very long time to run are enabled to produce results in a short time by optimizing processor cores. Threading method is widely used especially in artificial intelligence, big data analysis and machine learning based applications.

With Python Threading, processes that require very high computational capacity are distributed to the cores of the server processor and finalized faster. Since the processes shared to the processor cores are optimized, the result will be achieved in a shorter time.

Index
Optimization with Python Threading Library
The ability to compute simultaneously by distributing the load on the processor. Generally, this method can be used if you are not familiar with the hardware on which the program will run. Multiple runs can be done in Parallel or Concurrent by distributing the load to the cores.
It is mostly used in mobile application development.
Measuring Processing Speed without Threading
For this, let’s import the python threading module but calculate the processing time without threading.
import threading
import requests as req
import time
def get_web(urls):
start_time = time.time()
json_data = []
for url in urls:
json_data.append(req.get(url).json())
end_time = time.time()
dif_time = end_time - start_time
print(f"Time: {dif_time}")
return json_data
urls = ['https://postman-echo.com/delay/2'] * 8 # 8 times request delay 2 seconds
get_web(urls) # Time: 24.787731170654297 seconds
PythonIn the code lines above, the data source named https://postman-echo.com/delay/2 was requested to wait for 2 seconds and run 8 times in total to calculate the total processing time. The transactions were finalized in a total of 24 seconds.
Measuring Processing Speed Using Threading
Now let’s try to do this task at the same time by parallel partitioning on the processor. Let’s calculate the processing time using the Python Threading library. For this we will need to define a class and a few functions.
import threading
import requests as req
import time
## Use threading for this class and function:
class ThreadingOptimizer(threading.Thread):
json_data = []
def __init__(self,url): ## for inheritance
super().__init__()
self.url = url
def run(self):
response = req.get(self.url)
self.json_data.append(response.json())
return self.json_data
def get_web_thread(urls):
start_time = time.time()
threads = []
for url in urls:
t = ThreadingOptimizer(url)
t.start()
threads.append(t)
for t in threads:
t.join()
print(t)
end_time = time.time()
dif_time = end_time - start_time
print(f"Time: {dif_time}")
urls = ['https://postman-echo.com/delay/2'] * 8 # 8 times request delay 2 seconds
get_web_thread(urls)
PythonThe operations to be performed in the special run function defined in the class called ThreadingOptimizer are calculated quickly with the threading procedure.
When we calculate the same operation without Threading, it takes 24 seconds, while it takes 3.3 seconds with Threading support.
Coroutines and Tasks (Asynchronous)
In order to use this threading procedure you need to import the asyncio and aiohttp libraries. With this method, thread processes can stop or resume at any time.
async: indicates that an asynchronous threading will be written.
await: indicates to wait for the result of a running asyncio operation.
import threading
import requests as req
import time
import asyncio
import aiohttp
async def get_web_async_wrapper(urls):
start_time = time.time()
jason_data = []
async with aiohttp.ClientSession() as session:
for url in urls:
async with session.get(url) as resp:
jason_data.append(await resp.json())
end_time = time.time()
dif_time = end_time - start_time
print(f"Time: {dif_time}")
return jason_data
urls = ['https://postman-echo.com/delay/2'] * 8 # 8 times request delay 2 seconds
asyncio.run(get_web_async_wrapper(urls))
PythonRecursion Process (Nested Rerun)
It is a very useful Python feature that we can translate as nested rerunable in Turkish. You can perform many operations that can be done in a loop more easily with the Recursive method.
In the following example, let’s write an application that calculates mathematical factorial first with loop logic and then with Recursion logic.
Let us remind you for those who do not know factorial calculus:
5! : 5 It means factorial.
Calculation: 5! = 5x4x3x2x1 = 120
With While Loop:
def FactLoop(number):
num = 1
while (number!=0): # zero point control
if num == 0:
break
else:
num = num * number # non recursion, Loop methods
number-=1
return num
print(f"Fact Recursive Result: {Fact(5)}") # 120
PythonWith the Recursive Method:
def Fact(number):
if number == 0: # zero point control
return 1
else:
return number * Fact(number-1) # Recursion
print(f"Fact Recursive Result: {Fact(5)}") # 120
PythonAs can be seen, 120 results are obtained for a factorial of 5 in both ways. However, the Recursive method wins with fewer lines of code.
Just like in Python Threading, you can write much less code with the Recursive, or nested re-running technique, and get many looping operations done.