Multithreading and Multiprocessing in Python
Python provides powerful tools to perform multiple tasks simultaneously using Multithreading and Multiprocessing. These concepts are widely used to improve performance and efficiency in real-world applications.
Why Concurrency is Needed?
Concurrency helps when:
- Tasks take time (I/O operations)
- Multiple independent tasks need to run
- System resources must be utilized efficiently
Multithreading in Python
Multithreading allows multiple threads to run within the same process. All threads share the same memory space.
Python uses the threading module to create and manage threads.
Simple Multithreading Example
import threading
import time
def task():
print("Task started")
time.sleep(2)
print("Task completed")
thread1 = threading.Thread(target=task)
thread2 = threading.Thread(target=task)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print("Main thread finished")
Thread with Arguments
def print_numbers(name):
for i in range(3):
print(name, i)
t1 = threading.Thread(target=print_numbers, args=("Thread-1",))
t2 = threading.Thread(target=print_numbers, args=("Thread-2",))
t1.start()
t2.start()
Global Interpreter Lock (GIL)
Python has a Global Interpreter Lock (GIL) which allows only one thread to execute Python bytecode at a time.
Because of GIL:
- Multithreading is best for I/O-bound tasks
- Not ideal for CPU-bound tasks
Use Cases of Multithreading
- File reading and writing
- API calls
- Web scraping
- Automation testing (parallel browser actions)
Multiprocessing in Python
Multiprocessing runs multiple processes, each with its own memory space. It bypasses the GIL and uses multiple CPU cores.
Python provides the multiprocessing module.
Simple Multiprocessing Example
from multiprocessing import Process
import time
def task():
print("Process started")
time.sleep(2)
print("Process completed")
p1 = Process(target=task)
p2 = Process(target=task)
p1.start()
p2.start()
p1.join()
p2.join()
print("Main process finished")
Multiprocessing with Arguments
from multiprocessing import Process
def square(num):
print(f"Square of {num} is {num*num}")
processes = []
for i in range(5):
p = Process(target=square, args=(i,))
processes.append(p)
p.start()
for p in processes:
p.join()
Multithreading vs Multiprocessing
| Multithreading | Multiprocessing |
|---|---|
| Uses threads | Uses processes |
| Shares memory | Separate memory |
| Affected by GIL | Not affected by GIL |
| Best for I/O-bound tasks | Best for CPU-bound tasks |
Multithreading in Automation Testing
def run_test(test_name):
print("Running", test_name)
tests = ["LoginTest", "PaymentTest", "SearchTest"]
threads = []
for test in tests:
t = threading.Thread(target=run_test, args=(test,))
threads.append(t)
t.start()
for t in threads:
t.join()
Multiprocessing in Automation Testing
from multiprocessing import Process
def run_test(test_name):
print("Executing", test_name)
tests = ["ChromeTest", "FirefoxTest"]
for test in tests:
p = Process(target=run_test, args=(test,))
p.start()
Best Practices
- Use multithreading for I/O-bound operations
- Use multiprocessing for CPU-intensive tasks
- Always use join() to avoid orphan threads/processes
- Avoid shared data issues
Common Interview Questions
- What is the difference between threading and multiprocessing?
- What is GIL?
- When to use multithreading?
- When to use multiprocessing?
- Is multiprocessing faster than multithreading?
Conclusion
Multithreading and multiprocessing help build high-performance Python applications. Choosing the right approach depends on whether the task is I/O-bound or CPU-bound.
👉 Learn more advanced Python concepts on way2testing.com
No comments:
Post a Comment