Application Development Using Python
Application Development Using Python
Origin: Python was created by Guido van Rossum at the Centrum Wiskunde & Informatica (CWI) in the
Netherlands, with development starting in December 1989 as a successor to the ABC programming language
First Release: The initial version, Python 0.9.0, was launched in 1991. It introduced key features such as
exception handling, functions, and core data types (lists, dictionaries, strings), along with a basic module
system.
Major Milestones:
o Python 1.0 (1994): Brought functional programming constructs like lambda, map, filter, and reduce,
as well as improved exception handling and object-oriented programming basics
o Python 2.0 (2000): Introduced list comprehensions, garbage collection, and full Unicode support,
making Python more powerful and accessible for international use
o Python 3.0 (2008): A significant overhaul to remove legacy issues, improve the language's core
syntax, and ensure robust Unicode and text processing. Not backward-compatible with Python.
Leadership: Guido van Rossum was known as Python’s “Benevolent Dictator for Life” (BDFL), steering its
development until 2018, after which the Python Software Foundation and a steering council took over
project governance
Importance of Python
Readability & Simplicity: Python's clear, English-like syntax emphasizes readability, making it easy for
beginners and reducing maintenance overhead for professionals
Extensive Community & Libraries: Open-source and supported by a vast developer community, Python
boasts a rich ecosystem of libraries and frameworks for almost every field
Cross-Platform & Versatile: Runs on all major operating systems and adapts easily to various application
domains, from scripting to enterprise solutions.
Education and Research: Widely used for teaching programming concepts, due to its gentle learning curve
and expressive clarity
Applications of Python
Web Development: Frameworks like Django and Flask streamline rapid development of robust web
applications.
Data Science & Analytics: Libraries such as Pandas, NumPy, SciPy, and Matplotlib power data analysis,
statistics, and visualization.
Artificial Intelligence & Machine Learning: Used extensively with libraries like TensorFlow, PyTorch, and
Scikit-learn for tasks ranging from natural language processing to computer vision.
Automation & Scripting: Simplifies automation of repetitive tasks and system administration with concise
scripts.
Desktop GUI Development: Tools like Tkinter and PyQt enable creation of cross-platform desktop
applications.
Networking & IoT: Supports network programming and Internet of Things development for both prototyping
and production.
Game Development: Libraries such as Pygame are used for simple game creation and prototyping.
Education: Frequently chosen as the first language in programming courses at schools and universities.
Feature Description
Simple, Readable Syntax Code looks like pseudocode, easy to write and understand
Extensive Standard Library Comprehensive modules for everything from math to web protocols
Portable & Cross-Platform Runs unchanged on Windows, macOS, Linux, and more
Open Source Free to use, modify, and distribute; vibrant community support
Extensible & Embeddable Integrate easily with C/C++ and other languages for performance boosts
Unit-1
Definition: A Python object is a concrete instance of a class. It bundles together data (attributes) and
behaviors (methods)—in other words, values and operations that can be performed on those values.
Key Idea: Think of a class as a blueprint (like a recipe), and an object as the actual item created using
that blueprint (like a cake baked from the recipe).
Behavior (methods): Functions defined in the class to operate on the object’s data.
Basic Example
class Dog:
def bark(self):
my_dog = Dog("Rocky", 5)
print(my_dog.age) # Output: 5
my_dog is an object with its own name and age, and it can bark()
Python Standard Types
Python includes a rich set of standard (built-in) data types that classify and manage all kinds of values.
Each data type supports specific operations and behaviors.
In addition to the most commonly discussed types (such as integers, strings, lists, and dictionaries), Python
includes several other built-in types that enhance its versatility and power.
Overview Table
1. Binary Types
bytes: Immutable sequences of bytes, often used for binary data or when working with files and
network resources.
b = b'example'
ba[0] = 68
memoryview: Provides a memory-level view of objects like bytes and bytearray without copying
data, enabling fast slicing and manipulation.
mv = memoryview(b'hello')
2. Set Types
s = {1, 2, 3}
frozenset: Like set, but immutable and hashable (usable as dictionary keys).
fs = frozenset([3, 4, 5])
3. Range Type
r = range(0, 10, 2)
4. Boolean Type
flag = True
5. None Type
None is a special constant representing “no value” or “null”. There is a single instance of this
type, None, commonly used for default parameters or as a placeholder.
result = None
6. Complex Numbers
z = 2 + 3j
Internal Types in Python
Python’s internal types are specialized objects that play crucial roles within the interpreter but are rarely
used directly in everyday programming. These types handle underlying execution, error tracking, slicing,
and internal mechanisms required by the Python runtime environment.
1. Code Objects
2. Frame Objects
Represent individual execution contexts (like a particular call in the call stack).
Contain information about local/global variables, the code object being executed, and where
execution currently is.
3. Traceback Objects
4. Slice Objects
Enable advanced sequence slicing and custom behavior, especially in user-defined data structures.
5. Ellipsis Object
Written as ....
Arithmetic Operators
Comparison Operators
Assignment Operators
Logical Operators
Membership Operators
Identity Operators
Example Code
# Arithmetic
a, b = 10, 4
# Membership
# Identity
x = [1,2]
y=x
print(x is y) # True
Standard Type Built-in Functions in Python
Python provides a robust set of built-in functions that work closely with its standard (built-in) data types.
These functions streamline type conversion, manipulation, inspection, and utility operations for numbers,
strings, lists, dictionaries, sets, and other core structures.
Numeric Functions
Dicts: .keys(), .values(), .items() return keys, values, and key-value pairs respectively.
Examples
# Type conversion
x = "10"
y = int(x) # y = 10
# Numeric operation
print(abs(-7)) # Output: 7
# Sequence function
print(len(names)) # Output: 2
# Dictionary inspection
d = {'one': 1, 'two': 2}
Python’s standard types are grouped into broad categories based on the kind of data they represent and the
operations they support. This organization helps in understanding their use and distinguishing their
behaviors in programming.
Major Categories of Standard Types
Numeric Types
Sequence Types
range: Immutable sequence, typically used for looping a specific number of times.
Mapping Type
dict: Collection of key-value pairs, keys are unique and usually immutable.
Set Types
set: Mutable, unordered collection of unique, hashable items.
Boolean Type
bool: Represents truth values. Only two instances: True and False.
Binary Types
memoryview: Provides a view of the memory of another binary object without copying.
None Type
NoneType: Singleton type with a single value, None, representing “no value” or “null”.
Not all forms of data or constructs are natively supported as distinct data types in Python. While Python
features a rich set of standard (built-in) types, there are categories or behaviors where "unsupported types"
commonly arise, particularly in advanced or cross-platform contexts.
Types that may exist in specialized packages but are not part of Python’s built-in type system.
When exchanging data with databases (e.g., PostgreSQL, Amazon Redshift), or dealing with file
formats or APIs, certain types such as arrays, geometric types, enumerations, composite types, or
proprietary time formats may not map directly to Python types.
Pandas DataFrames may show columns with types (like [Link] or nested lists) that are stored
as generic object, leading to unsupported operations or errors in data processing workflows.
Some types from platforms like HDF5, XML, or binary files might not have native Python
representations.
Python's standard library does not provide types for advanced database features such as custom
enumerations or geometric data without additional packages.
Libraries like NumPy or Pandas often require specific types (e.g., numerical arrays), and will reject
unsupported or ambiguous types, raising errors if you attempt to assign incompatible values.
Python provides comprehensive support for working with numbers, enabling developers to handle a wide
variety of mathematical operations and tasks. The three primary numeric types in Python
are integers, floating point numbers, and complex numbers.
Examples:
python
x = 42
y = -1000
z=0
Can also be written in scientific notation using e or E (e.g., 1.5e2 for 150).
Examples:
python
pi = 3.14159
temperature = -15.6
Examples:
python
z1 = 2 + 3j
z2 = 10j
z3 = -1.4 + 0j
The .real and .imag attributes access real and imaginary parts.
python
r = [Link] # 2.0
i = [Link] # 3.0
Numeric Operators
Type Conversion:
Absolute Value:
Divmod:
Rounding:
math: Functions for floating-point and integer math (e.g., sqrt, sin, log). Does NOT support complex
numbers.
Example Usage
import math
import cmath
# Integers
a=7
b=2
# Floats
x = 5.6
y = 2.5
z = x ** y # Exponentiation
# Complex
c = 3 + 4j
conjugate = [Link]() # 3 - 4j
complex_root = [Link](-1) # 1j
Summary Table
Strings
Key Features:
Supports indexing (s), slicing (s[1:3]), concatenation ('a' + 'b' → 'ab'), repetition
('a'*3 → 'aaa').
Example:
s = "Python"
print(s[0]) # Output: P
Lists
Key Features:
Elements can be of any type—mixed types are allowed ([1, 'a', 3.0]).
Support for indexing, slicing, appending (.append()), removing (.remove(), .pop()), inserting,
and more.
Example:
numbers = [1, 2, 3]
[Link](4) # [1, 2, 3, 4]
numbers[0] = 99 # [99, 2, 3, 4]
Tuples
Key Features:
Example:
Dictionaries
Key Features:
Access via keys (d['key']), supports various methods (.get(), .items(), .keys(), .values()).
Example:
ages['Charlie'] = 35
Sets
Key Features:
No duplicate items.
Supports mathematical set operations: union (|), intersection (&), difference (-).
Example:
Truthiness
Values considered "False": None, False, zero of any numeric type, empty sequences ([], '', ()) or
collections ({}).
Sorting
nums = [3, 2, 1]
print(sorted(nums)) # [1, 2, 3]
List Comprehensions
Example:
python
Control flow determines the order in which instructions in a Python program are executed. Python uses
control flow statements to enable both decision-making (conditional execution) and repetition (loops),
allowing programs to adapt their behavior based on input or data.
[Link]-Making Statements
if Statement
python
x=5
if x > 3:
2. if-else Statement
if number > 0:
print("Positive number")
else:
If the user enters 10, "Positive number" is shown. If 0 or less, "Not a positive number" appears.
3. if-elif-else Statement
python
a = 33
b = 33
if b > a:
elif a == b:
else:
Only the first true condition’s block is executed; the rest are skipped. Here, because a == b, only "a and
b are equal" is printed.
python
score = 75
print("Excellent")
print("Good")
print("Average")
else:
print("Needs improvement")
for Loop
Used to iterate over sequences (like lists, tuples, dictionaries, strings, or ranges).
Example:
python
print(fruit)
while Loop
Example:
python
i=0
while i < 5:
print(i)
i += 1
# Output: 0 1 2 3 4
Loops like these enable tasks such as repeated calculations or data processing.
continue: Skips the rest of the loop body and moves to the next iteration.
Overview
Iterators and generators are essential constructs in Python for working with sequences and data streams.
They enable efficient data processing, particularly when dealing with large or potentially infinite datasets.
What Is an Iterator?
__next__(): Returns the next value from the sequence. If there are no further items, it
raises StopIteration.
Iterators are usually used to loop over collections such as lists or custom objects.
Example:
python
nums = [1, 2, 3]
it = iter(nums)
print(next(it)) # 1
print(next(it)) # 2
What Is a Generator?
A generator is a convenient way to create an iterator using a function with the yield statement.
When called, a generator function returns a generator object, which can yield a sequence of values,
generating each on-the-fly without holding the entire data in memory.
Generators are excellent for memory efficiency, especially with large or infinite data streams.
Example:
python
def countdown(n):
while n > 0:
yield n
n -= 1
print(number)
# Output: 3, 2, 1
Each call to yield produces the next value in the sequence and resumes from that point on the next
iteration.
File Objects
A file object in Python represents an open file and provides methods and attributes to interact with files
stored on disk. File objects are essential for reading from, writing to, and managing files.
The open() function is the gateway to file handling in Python. It returns a file object and requires at least the
filename; an optional mode string determines how the file is used.
Common Modes:
Mode Description
Close file after use with [Link]() or (preferably) use a with statement for automatic management:
data = [Link]()
Method Description
Example:
[Link]('Hello\n')
line = [Link]()
Attribute Description
Standard Files
Object Description
These are available via the sys module and can be redirected as needed.
Command-line Arguments
Python scripts can access command-line arguments via the [Link] list. The first item is the script name;
subsequent items are user-provided arguments.
Example:
import sys
Python's standard library includes modules for advanced file and directory operations:
Example:
import os
[Link]('[Link]', '[Link]')
File Execution
[Link](command): Runs a system-level command, which could launch or execute files via the
command line.
Exceptions in Python are events that disrupt the normal flow of a program’s execution. They typically
represent errors—like dividing by zero, missing files, or failed type conversions. When not managed,
exceptions cause the program to terminate and display an error.
Detecting Exceptions
Python’s approach to error detection is to "raise" exceptions when it encounters such issues.
Basic Syntax
try:
risky_operation()
except SpecificException as e:
handle_the_error()
result = 10 / number
except ZeroDivisionError:
except ValueError:
Here, different messages are shown depending on the error: division by zero or invalid input.
Use a general except Exception clause as a safety net, but use it carefully to avoid swallowing unexpected
errors:
try:
do_something()
except Exception as e:
try:
f = open("[Link]")
except FileNotFoundError:
else:
finally always runs, making it ideal for resource management (e.g., closing files).
Context management in Python refers to a programming pattern used to setup and teardown resources
automatically. It ensures that resources such as files, network connections, or database sessions are properly
acquired and released, even if errors or exceptions occur during execution.
The most common form of context management is the with statement, which works with special context
manager objects that define their behavior upon entering and exiting a runtime context.
Python has an established protocol that any class can implement in order to act as a context manager. This
protocol requires the implementation of two special methods:
When a with statement is executed, Python calls the context manager's __enter__() method, which
can perform setup operations (e.g., opening a file, acquiring a lock) and return an object to be used in
the block.
The code inside the with block runs, using the resource provided by __enter__().
After the block finishes (normally or via exception), Python calls __exit__(), which handles cleanup
(e.g., closing the file, releasing the lock).
If an exception occurred, the exception details (exc_type, exc_value, traceback) are passed
to __exit__(). Returning True suppresses the exception; returning False (or not returning) propagates
it.
Ambiguity: Two different exceptions from different modules with the same string value could not be
distinguished.
Extensibility: Class-based exceptions allow custom error objects with attributes and methods,
enhancing error reporting and handling.
In current Python, all exceptions are class instances (typically derived from Exception or its
subclasses).
You can still extract the string message of an exception using str(e) in an except clause.
try:
except Exception as e:
Raising exceptions is the way to deliberately signal an error or unusual situation in your code. This
interrupts normal execution and transfers control to the nearest appropriate exception handler, if one exists.
If not caught, the program terminates with an error message.
Syntax: raise
You can define your own exception class by inheriting from Exception:
class MyError(Exception):
pass
Inside an except block, you may use raise with no arguments to re-raise the current exception:
try:
1/0
except ZeroDivisionError:
Assertions are statements in Python that check if a condition is true during the execution of a program. If
the condition evaluates to True, the program continues running as normal. If it is False, Python raises
an AssertionError and halts execution unless the exception is handled.
Useful for validating program invariants, checking function arguments, and ensuring intermediate
states are as expected.
Syntax
assert condition
Examples:
x = 10
x = -5
Standard exceptions are pre-defined error classes in Python that represent common error conditions and
unusual events during program execution. They provide a unified way to report and handle errors, making
code more maintainable and robust. All standard exceptions derive from the BaseException class and are
available in the Python Standard Library12.
Exception Description
Creating Custom Exceptions:To define your own exception, subclass Exception (or one of its subclasses):
class MyCustomError(Exception)
pass
You can add custom attributes and methods to enhance your error reporting.
Use custom exceptions to signal application-specific problems, and maintain clean, predictable error-
handling logic across your codebase.
Separation of Concerns: Exceptions allow error-handling code to be separated from regular logic,
increasing clarity and reducing clutter.
Graceful Failure: Programs can recover, report, or clean up when errors arise, rather than
terminating unexpectedly.
Standardized Error Reporting: Consistent mechanisms for indicating diverse failure modes (e.g.,
I/O problems, invalid user input).
Propagation: Errors naturally propagate up the call stack, allowing higher-level handlers to decide
on recovery strategies.
As Python codebases grow more complex—especially with file/network operations, external APIs,
and user inputs—robust error handling becomes more critical.
Exception mechanisms empower developers to build resilient software that can anticipate, capture,
and handle operational failures and unexpected states.
Modern exceptions, with their rich hierarchy and instance attributes, streamline debugging and
provide precise control over different types of software errors.
Python's sys module offers tools for interacting closely with the interpreter, including controlling how
exceptions are reported and how standard error streams are managed.
sys.exc_info()
Returns a tuple (type, value, traceback) representing the most recent exception caught by
an except clause in the current thread.
[Link]
[Link]
Standard error stream. By default, uncaught exceptions and tracebacks are printed here.
You can redirect [Link] to log exceptions to files or GUIs, which is useful for error
monitoring and debugging in deployed applications.
[Link]()
Raises a SystemExit exception, triggering interpreter exit, which can be intercepted for clean-
up.
import sys
[Link] = custom_excepthook
Example:
import sys
try:
1/0
except ZeroDivisionError:
Redirecting [Link] allows integration with logs, graphical programs, or remote monitoring tools,
especially in server or GUI applications.
Several standard library modules extend and complement core exception management:
import traceback
try:
1/0
except Exception:
A module is a reusable unit of code—typically a single .py file—that encapsulates functions, classes,
and variables.
Each .py file you write is a module; for example, [Link] creates a math module.
Modules can also be collections of files within a structured directory (see Packages).
Importing a module runs its code and makes its defined names available to other scripts or modules.
Namespaces
Modules themselves act as namespaces: everything defined within a module (including functions,
classes, and variables) lives in its own module-level namespace.
Namespaces prevent naming conflicts between different parts of a program, as names in different
modules do not collide.
Importing Modules
Use the import statement to bring an entire module into the current namespace:
python
import math
Importing a module only runs its top-level code once per session, caching the namespace for later
use.
globals() / locals(): Return dictionaries representing the current global and local namespaces.
Packages
A package is a method for organizing related modules in directories using a hierarchical, dotted-
module-name syntax (e.g., [Link]).
Packages support submodules and nested packages, enabling extensive code organization.
Namespace packages—introduced in Python 3.3—let you distribute a single logical package across
multiple directories, omitting the __init__.py file within the namespace directory. This allows for
extensible plugin systems and modular organization.
text
__init__.py
effects/ # Subpackage
__init__.py
[Link] # Submodule
[Link]
formats/
__init__.py
[Link]
[Link]
Module Reloading: Use the [Link](module) function to reload a module’s code. Useful
during development.
Custom Module Search Path: Modify [Link] to add or prioritize directories in Python’s search for
modules or packages.
Module Aliasing: Use import module as alias to assign a custom name to a module in your script.
python
import numpy as np
Introspection: Inspect a module’s contents and docstrings using dir() and help().
Feature Description
Module Single .py file; top-level namespace
Package Directory with __init__.py and submodules
Namespace Package Directory without __init__.py; can span multiple locations/distributions
Importing Module import module – everything under the module’s namespace
Importing Attribute from module import name – imports specific items directly
Module Inspect Tools dir(), help(), __import__(), etc.
Module Organization Use subdirectories, submodules, namespace packages for scalability and
clarity
Python’s modules and packages provide robust tools for code organization, namespace management, and
scalable application design, supporting everything from simple to highly modular projects.
Unit-3
Introduction to Regular Expressions
A regular expression (RegEx) is a specialized sequence of characters that describes a search pattern for
string matching and manipulation. In Python, the re module provides extensive support for regular
expressions, enabling search, pattern matching, substitution, splitting, and other text processing tasks.
import re
pattern = r'^a...s$'
test_string = 'abyss'
if result:
print("Search successful.")
else:
print("Search unsuccessful.")
Here, ^a...s$ matches any five-letter string starting with 'a' and ending with 's'.
Raw string (r''): Prefix regular expressions with r to treat backslashes literally, which is essential when
working with special characters and escape sequences.
Ordinary Characters
Most letters and numbers match themselves (e.g., cat matches 'cat').
Regular expressions become powerful when combining ordinary and special characters.
Metacharacters
Example:
import re
pattern = r'\d{3}'
A backslash \ escapes a metacharacter if you want to match it literally (e.g., \. matches a period).
Metacharacter Description
. Any character (except newline)
^ Start of string
$ End of string
* Zero or more repetitions
+ One or more repetitions
? Zero or one repetition
{} Exact or range of repetitions
[] Set or range of characters
\ Special sequence or escape
() Grouping
Key Points
Raw strings should be used to prevent Python from interpreting escape sequences.
Special sequences make it easy to find classes of characters like digits or whitespace.
Regular expressions (regex or regexp) are specialized patterns that allow for advanced search and
manipulation of text. In Python, all regular expression capabilities are provided by the built-in re module,
enabling robust text processing for searching, matching, splitting, and replacing content in strings.
python
import re
You then apply one of the core functions from the re module to work with patterns and text.
Core Functions of re
pattern = r"\d+"
Regular expressions use metacharacters to build flexible matching rules. Below are some of the most
important ones:
Symbol Meaning
. Any character except newline
^ Start of string
$ End of string
* Zero or more repetitions
+ One or more repetitions
? Zero or one repetition
{n} Exactly n repetitions
{n,} n or more repetitions
{n,m} Between n and m repetitions
[] Matches one character from the set/range inside brackets
` `
() Groups a pattern and captures the match
\d Digit character
\w Word character (alphanumeric or underscore)
\s Whitespace character
\b Word boundary
\ Escape for special/metacharacter
Example:
To match a string that starts with "The" and ends with "Spain":
What Is Multithreading?
Multithreading in Python is a programming technique that enables multiple threads (lightweight sub-
processes) to execute concurrently within a single process. Each thread represents an independent sequence
of instructions, sharing the same memory space as other threads in the same process. This enables a program
to handle multiple tasks at once, such as managing user input, performing I/O operations, or updating a user
interface—all without waiting for each task to finish sequentially.
Python offers two main approaches for concurrent and parallel execution:
Threads: Lightweight units of execution within a single process, sharing the same
memory space.
Processes: Fully independent instances of the Python interpreter, each with their own memory
space.
Understanding the difference is vital for choosing the right tool for I/O-bound versus CPU-bound
tasks.
Threads
Definition: A thread is a sequence of instructions within a process; multiple threads share the
same memory and resources.
Memory: Shared with the parent process and other threads within the same process, enabling
efficient inter-thread communication.
Use case: Best suited for I/O-bound tasks (file operations, network requests), as threads can
perform tasks concurrently even while waiting for external resources.
Limitations:
Subject to Python’s Global Interpreter Lock (GIL), meaning only one thread executes
Python bytecode at a time; this limits multithreaded speedup for CPU-bound
operations.
Processes
Definition: A process is a separate, isolated instance of the Python interpreter. Processes do not
share memory.
Memory: Completely separated from other processes (no shared memory by default); inter-
process communication requires special mechanisms (pipes, queues).
Use case: Ideal for CPU-bound tasks (intensive number crunching) because each process has
its own GIL and can achieve true parallelism across multiple CPU cores.
Limitations:
Practical to create tens of processes (not hundreds or thousands) due to system resource
constraints.
Comparison Table
Improved Responsiveness: User interfaces or servers remain responsive by delegating tasks like
computation or waiting for input/output to separate threads.
Resource Sharing: Threads easily share memory and state, simplifying communication compared to
processes.
Lower Overhead: Threads are lighter than processes and do not require as much memory or system
resources.
Limitations
Global Interpreter Lock (GIL): Only one native thread executes Python bytecode at a time; this
means no true parallelism for CPU-bound code.
Race Conditions: Multiple threads accessing shared data can lead to unpredictable results unless
access is synchronized.
Debugging Complexity: Concurrent code tends to be more challenging to test and debug.
The Global Interpreter Lock (GIL) is a mutex—a kind of lock—that restricts execution of Python
bytecode to a single thread at any given time, even on multi-core systems. This means that, within a
single Python process (for example, using CPython, the standard Python implementation), only one
thread can execute Python code at once, regardless of how many threads are created
Simplicity for Memory Management: CPython uses reference counting for garbage collection. The
GIL simplifies protection of internal data structures and prevents race conditions by ensuring only
one thread manipulates reference counts or other interpreter internals at a time.
Integration with C Extensions: Many Python libraries are written in C and may not be thread-safe.
The GIL provides a stable environment for these extensions, making Python extensibility easier.
CPU-bound Programs: In CPU-intensive tasks, the GIL prevents full utilization of multiple CPU
cores with threads, making multithreaded Python programs unable to achieve true parallelism for
Python code. Only one thread executes Python bytecode at a time.
I/O-bound Programs: The effects of the GIL are less pronounced for I/O-bound workloads (such as
web servers or file/network operations), since threads often spend time waiting for input/output
operations outside the Python interpreter, where the GIL can be released, allowing other threads to
run
Parallelism Bottleneck: The GIL is considered a major limitation for Python in high-performance,
multi-core, CPU-bound computing scenarios.
Additional Overhead: Can lead to slower performance even in multi-threaded code, due to the cost
of switching and locking for the GIL, especially on multi-core hardware.
Complex Extensions: C/C++ extensions to Python must be GIL-aware, sometimes releasing and
reacquiring the GIL as needed for CPU-intense work
_thread module (formerly just thread in Python 2): The original, low-level thread interface.
threading module: The modern, high-level threading interface built on top of _thread,
recommended for almost all Python applications.
Interface: Exposes basic functions like start_new_thread() to run a callable in a new thread.
Drawbacks: Minimal features—no thread objects, synchronization primitives (only basic locks), or
exception handling for threads.
Use cases: Very rarely used in modern code except for embedding or maintaining legacy
applications.
Example:
import _thread
def worker():
print("Worker thread")
_thread.start_new_thread(worker, ())
Purpose: Provides a robust, object-oriented API for creating and managing threads and
synchronization.
Key Features:
Synchronization Primitives: Includes Lock, RLock, Event, Condition, Semaphore for safe
data sharing between threads.
Example:
python
import threading
def task(arg):
t = [Link](target=task, args=(42,))
[Link]()
Subclassing Thread
You can subclass Thread and override the run method for custom behavior:
python
class MyThread(Thread):
def run(self):
print("Thread is running")
t = MyThread()
[Link]()
[Link]()