Python
Python
B.Sc (V Semester)
Application Development using Python
UNIT-I
Python basics, Objects – Python Objects, Standard Types, Other Built-in Types, Internal Types,
Standard Type Operators, Standard Type Built-in Functions, Categorizing the Standard Types,
Unsupported Types.
Numbers – Introduction to Numbers, Integers, Floating Point Real Numbers, Complex
Numbers, Operators, Built-in Functions.
Sequences – Strings, Lists, and Tuples, Dictionaries and Set Types.
Control Flow, Truthiness, Sorting, List Comprehensions, Generators and Iterators.
UNIT-II
Files – File Objects, File Built-in Function ( open()), File Built-in Methods, File Built-in
Attributes, Standard Files, Command-line Arguments, File System, File Execution.
Modules – Modules and Files, Namespaces, Importing Modules, Importing Module Attributes,
Module Built-in Functions, Packages.
UNIT-III
Multithreaded Programming – Introduction, Threads and Processes, Python Threads, and the
Global Interpreter Lock, Thread Module, Threading Module.
UNIT-IV
GUI Programming: Introduction, Tkinter and Python Programming, Brief Tour of Other GUIs.
Web Programming: Introduction, Web Surfing with Python, Creating Simple Web Clients,
Advanced Web Clients, CGI-Helping Servers Process Client Data, Building CGI Application,
Advanced CGI, Web (HTTP) Servers.
UNIT-V
Text Book(s)
1. Core Python Programming, Wesley J. Chun, Second Edition, Pearson.
2. Think Python, Allen Downey, Green Tea Press.
UNIT-I
INTRODUCTION
FEATURES
Python works on different platforms (Windows, Mac, Linux, Raspberry Pi, etc).
Python has a simple syntax similar to the English language.
Python has syntax that allows developers to write programs with fewer lines than
some other programming languages.
Python runs on an interpreter system, meaning that code can be executed as soon
as it is written.
Python can be treated in a procedural way, an object-oriented way or a functional
way.
Python was designed for readability, and has some similarities to the English
language with influence from mathematics.
Python uses new lines to complete a command, as opposed to other programming
languages which often use semicolons or parentheses.
Python relies on indentation, using whitespace, to define scope; such as the scope
of loops, functions and classes. Other programming languages often use curly-
brackets for this purpose.
STANDARD TYPES
Python's standard types, also referred to as built-in data types, categorize various kinds of
data that can be manipulated within the language. Every piece of data in Python is an
object, and these standard types represent the classes from which these objects are
instantiated.
Numeric types:
int: Represents integer numbers (e.g., 5, -100).
float: Represents floating-point numbers (e.g., 3.14, 2.0).
complex: Represents complex numbers (e.g., 3 + 4j).
Sequence types:
str: Represents sequences of characters (text) (e.g., "hello", 'Python').
list: Represents ordered, mutable sequences of items (e.g., [1, 2, "three"]).
tuple: Represents ordered, immutable sequences of items (e.g., (1, 2, "three")).
range: Represents an immutable sequence of numbers, often used in loops
(e.g., range(5)).
Mapping type:
dict: Represents unordered collections of key-value pairs (e.g., {"name": "Alice",
"age": 30}).
Set types:
set: Represents unordered collections of unique, mutable items (e.g., {1, 2, 3}).
frozenset: Represents unordered collections of unique, immutable items.
Boolean type:
bool: Represents truth values, either True or False.
Binary types:
bytes: Represents immutable sequences of bytes.
bytearray: Represents mutable sequences of bytes.
memoryview: Provides a memory-efficient way to access the memory of other
binary objects.
BUILT-IN TYPES
Modules
The only special operation on a module is attribute access: m.name, where m is a module
and name accesses a name defined in m’s symbol table. Module attributes can be
assigned to
Function objects are created by function definitions. The only operation on a function
object is to call it: func(argument-list).
There are really two flavors of function objects: built-in functions and user-defined
functions. Both support the same operation (to call the function), but the implementation
is different, hence the different object types.
Methods
Methods are functions that are called using the attribute notation. There are two
flavors: built-in methods (such as append() on lists) and class instance method
Code Objects
A code object can be executed or evaluated by passing it to the exec() or eval() built-in
functions.
Type Objects
Type objects represent the various object types. An object’s type is accessed by the built-
in function type(). There are no special operations on types. The standard
module types defines names for all standard built-in types.
It is written as None.
There is exactly one ellipsis object, named Ellipsis (a built-in name). type(Ellipsis)
() produces the Ellipsis singleton.
Returned from comparisons and binary operations when they are asked to operate on
types they don’t support.It is written as NotImplemented.
Internal Objects
It defines about stack frame objects, traceback objects and slice objects
INTERNAL TYPES
In Python, "internal types" generally refer to objects that are part of the interpreter's
internal workings and are not commonly manipulated directly by typical application
programmers. These types are distinct from the standard built-in data types like integers,
strings, lists, or dictionaries.
The most prominent internal types include:
Code Objects:
These represent byte-compiled executable pieces of Python source code. They are
typically created by the compile() built-in function or found as attributes of function
objects (e.g., function.__code__). Code objects encapsulate the instructions but do not
contain execution environment details.
Frame Objects:
A frame object represents an execution frame in the Python call stack. It holds
information about the state of a function's execution, including local variables, global
variables, and the code object being executed within that frame. They can be accessed
through modules like sys or inspect.
Traceback Objects:
These objects are created when an exception occurs and contain information about the
call stack at the time of the exception, allowing for debugging and error reporting.
Slice Objects:
Created when using the slicing syntax (e.g., [start:stop:step]), these objects encapsulate
the start, stop, and step values used for sequence slicing.
Ellipsis Object:
Represented by ..., this is a singleton object primarily used in numerical computing
libraries like NumPy for advanced indexing and in type hints to indicate an arbitrary
number of arguments or dimensions.
Type Objects:
The type object itself represents the type of an object. For example, type(1) returns
the int type object. Type objects are callable and can be used to create new instances of
that type.
While these internal types are fundamental to Python's operation, direct interaction with
them is usually reserved for advanced tasks like introspection, debugging, or building
custom tools that manipulate the interpreter's behavior.
STANDARD TYPE OPERATORS
Python includes several categories of standard operators used to perform operations on
variables and values. These categories are:
1. Arithmetic Operators:
Used for mathematical calculations.
+ (Addition)
- (Subtraction)
* (Multiplication)
/ (Division - returns float)
// (Floor Division - returns integer)
% (Modulus - returns remainder)
** (Exponentiation)
2. Assignment Operators:
Used to assign values to variables.
4. Logical Operators:
Used to combine conditional statements. and (Logical AND), or (Logical OR), and not
(Logical NOT).
5. Identity Operators:
Used to check if two variables refer to the same object in memory. is and is not.
6. Membership Operators:
Used to check if a value is present within a sequence (e.g., string, list, tuple). in and not
in.
7. Bitwise Operators:
Used to perform operations on the individual bits of integer operands.
& (Bitwise AND), | (Bitwise OR), ^ (Bitwise XOR), ~ (Bitwise NOT), << (Left shift),
and >> (Right shift).
BUILT-IN FUNCTIONS
Python includes a set of "standard type built-in functions" that operate on various
fundamental data types and are always available for use without requiring any
imports. These functions provide core functionalities for working with numbers, strings,
collections, and other basic object types.
Type Conversion and Representation:
int(), float(), str(), list(), tuple(), dict(), set(): Used to convert values to their
respective data types or create new instances of these types.
bool(): Converts a value to its boolean equivalent.
Mathematical Operations:
abs(): Returns the absolute value of a number.
min(), max(): Return the minimum or maximum value from an iterable.
sum(): Calculates the sum of elements in an iterable.
round(): Rounds a number to a specified number of decimal places.
pow(): Returns the result of a number raised to a power.
Collection Operations:
len(): Returns the number of items in an object (e.g., length of a string, number
of elements in a list).
sorted(): Returns a new sorted list from the elements of an iterable.
reversed(): Returns a reverse iterator.
enumerate(): Adds a counter to an iterable, returning an enumerate object.
zip(): Combines multiple iterables element-wise.
Utility Functions:
print(): Outputs data to the console.
input(): Reads input from the user.
help(): Provides help information about an object.
dir(): Returns a list of names in the current scope or attributes of an object.
These are just a few examples, as Python offers a comprehensive set of built-in
functions to streamline common programming tasks across its standard data types.
CATEGORIZIING THE STANDARD TYPE
Python's standard built-in types can be categorized into several main groups based on
their characteristics and how they store and manage data.
Numeric Types:
These represent numerical values.
int: Integers (whole numbers, positive, negative, and zero).
float: Floating-point numbers (numbers with decimal points).
complex: Complex numbers, consisting of a real and an imaginary part (e.g., 3 +
4j).
Sequence Types:
These represent ordered collections of items.
Mapping Types:
These represent collections of key-value pairs.
dict: Dictionaries (unordered, mutable collections of unique keys mapped
to values).
Set Types:
These represent unordered collections of unique elements.
set: Sets (unordered, mutable collections of unique elements).
frozenset: Immutable versions of sets.
Boolean Type:
bool: Represents truth values, either True or False.
Binary Types:
These handle binary data.
bytes: Immutable sequences of bytes.
bytearray: Mutable sequences of bytes.
memoryview: Provides a "view" into another object's memory, allowing
access to its binary data without copying.
None Type:
NoneType: Represents the absence of a value. The sole value of this type
is None.
UNSUPPORTED TYPES
Logical operations:
Applying logical operators (and, or, not) in ways that are not intended for certain data
types, although Python often handles truthiness for various types.
Comparison operations:
While many types can be compared, some comparisons between fundamentally
different types might lead to unexpected behavior or errors in specific contexts.
Operations on NoneType:
Resolution:
To resolve "unsupported types" errors, it is crucial to ensure that the data types involved
in an operation are compatible. This often involves:
Type Conversion (Casting): Explicitly converting data from one type to another
(e.g., int(), str(), float()).
Data Validation: Checking the type of variables before performing operations.
Debugging: Tracing the origin of variables to understand their type and why they
might be incompatible.
INTRODUCTION TO NUMBERS
Numbers are fundamental data types in Python used to store numeric values and perform
mathematical operations. Python supports three primary numeric types:
Integers (int):
Represent whole numbers, both positive and negative, without any decimal point.
Ex
x = 10
print(type(x))
# Output: <class 'int'>
Ex
x = 1.23
print(type(x))
# Output: <class 'float'>
The 'complex' type of number indicates that it contains both an imaginary and real
component.
Ex
x = a+2b
print(type(x))
OPERATORS
Arithmetic operators
Assignment operators
Comparison operators
Logical operators
Identity operators
Membership operators
Bitwise operators
in
not in
BUILT-IN FUNCTIONS
Type Conversion:
int(): Converts a value to an integer.
float(): Converts a value to a floating-point number.
str(): Converts a value to a string.
list(), tuple(), dict(), set(): Convert iterables to their respective collection types.
Mathematical Operations:
abs(): Returns the absolute value of a number.
min(): Returns the smallest item in an iterable or the smallest of two or more
arguments.
max(): Returns the largest item in an iterable or the largest of two or more
arguments.
sum(): Calculates the sum of all items in an iterable.
round(): Rounds a number to a specified number of decimal places.
pow(): Returns the result of a number raised to a power.
Input/Output:
print(): Prints objects to the console.
input(): Reads input from the user.
SEQUENCES
Strings
Strings in python are denoted by either single quotation marks, or double quotation
marks.
'hello' is the same as "hello".
Ex
a = "Hello"
print(a)
List
o Lists are used to store multiple items in a single variable.
o Lists are one of 4 built-in data types in Python used to store collections of data, the
other 3 are Tuple, Set, and Dictionary, all with different qualities and usage.
o Lists are created using square brackets:
o List items are ordered, changeable, and allow duplicate values.
Ex
List1=[“abc”,23,’Male’]
print(a[2])
#Output: Male
Tuple
Dictionaries
Ex
x = {"brand": "Ford","model": "Mustang","year": 1964}
print(x)
#Output:{“brand": "Ford", "model": "Mustang", "year": 1964}
Set types
Ex
a = {1,2,3,3}
print(a)
#Output:{1,2,3}
CONTROL FLOW
Control flow in Python dictates the order in which instructions within a program are
executed. It allows for dynamic and responsive programs by enabling conditional
execution and repetitive tasks.
The main control flow constructs in Python include:
CONDITIONAL STATEMENTS (SELECTION):
These allow different blocks of code to be executed based on whether a certain
condition is true or false.
if: Executes a block of code only if the condition is true.
if-else: Executes one block if the condition is true, and another if it's false.
if-elif-else: Handles multiple conditions, checking them sequentially.
Ex
marks=80
result=””
If marks < 30:
result=”Failed”
eleif marks > 70:
result = “first division”
else:
result = “Passed”
print(result)
Output: first division
match-case: A more recent addition for pattern matching and executing code based
on matching patterns.
Ex
defcheckVowel(n):
match n:
case ’a’: return ‘Vowel’
case ’e’: return ‘Vowel’
case ’i’: return ‘Vowel’
case ’o’: return ‘Vowel’
case ’u’: return ‘Vowel’
case _: return ‘not a Vowel’
print(checkVowel(‘a’))
print(checkVowel(‘e’))
print(checkVowel(‘m’))
Output: Vowel
Vowel
Not a Vowel
LOOPS (REPETITION):
for loop: Iterates over a sequence (e.g., list, tuple, string, range) for each item.
Ex
numbers = [1,2,3,4,]
for x in numbers:
print(x)
Output: 1
2
3
4
TRUTHINESS
In Python, "truthiness" refers to the concept that every object has an inherent Boolean
value when evaluated in a Boolean context, such as in if statements, while loops, or
Boolean operations (and, or, not). This means that objects are implicitly converted
to True or False based on certain rules.
Rules
Falsy Values:
Numeric Zero: 0, 0.0, 0j (complex zero).
Empty Sequences and Collections: Empty strings (""), empty lists
([]), empty tuples (()), empty dictionaries ({}), empty sets (set()).
None: The None object explicitly represents the absence of a value
and is always falsy.
False: The Boolean literal False.
Truthy Values:
Non-zero Numbers: Any number other than zero (e.g., 1, -5, 3.14).
Non-empty Sequences and Collections: Any sequence or
collection containing at least one element (e.g., "hello", [1, 2], {'a':
1}).
True: The Boolean literal True.
Most Custom Objects: By default, instances of custom classes are
considered truthy unless they explicitly define
a __bool__ or __len__ method that returns a falsy value.
SORTING
Python provides two primary ways to sort data:
list.sort() method: This method sorts a list in-place, meaning it modifies the original
list directly and returns None. It is a method of the list object.
Ex
list1 = [3, 1, 4, 1, 5, 9, 2, 6]
list1.sort()
print(list)
Output: [1, 1, 2, 3, 4, 5, 6, 9]
Ex
list1.sort(reverse=True)
print(list1)
Output: [9, 6, 5, 4, 3, 2, 1, 1]
sorted() built-in function: This function takes any iterable (like a list, tuple, string,
etc.) and returns a new sorted list, leaving the original iterable unchanged.
Ex
tuple1 = (3, 1, 4, 1, 5)
sorted_list = sorted(tuple1)
print(sorted_list)
Output: [1, 1, 3, 4, 5]
print(tuple1)
Output: (3, 1, 4, 1, 5) (original tuple remains unchanged)
LIST COMPREHENSION
List comprehension in Python offers a concise and efficient way to create new lists
based on existing iterables (like lists, tuples, strings, or ranges). It provides a more
compact and often more readable alternative to traditional for loops for list creation and
transformation.
Syntax
new_list=[expression for item in iterables if condition]
COMPONENTS
expression:
This is the operation or transformation applied to each item from the iterable. The result
of this expression for each item becomes an element in the new_list.
item:
This is a temporary variable that represents each element from the iterable during the
iteration.
iterable:
This is the source sequence (e.g., a list, tuple, range, or string) from which elements are
processed.
if condition (optional):
This is a filtering condition. If present, only items that satisfy this condition are
included in the new_list.
Ex
numbers = [1, 2, 3, 4, 5, 6]
even_numbers = [num for num in numbers if num % 2 == 0]
BENEFITS
A generator function is a special type of function that returns an iterator object. Instead of
using return to send back a single value, generator functions use yield to produce a series
of results over time. This allows the function to generate values and pause its execution
after each yield, maintaining its state between iterations.
Lazy Evaluation:
Generators compute and yield values only when requested, rather than pre-calculating
and storing all values. This conserves memory, especially for large or infinite sequences.
yield keyword:
Generators are defined using the yield keyword instead of return. When a yield statement
is encountered, the generator pauses its execution, returns the yielded value, and saves its
state. When the generator is subsequently called (e.g., using next()), it resumes execution
from where it left off.
Iterator Protocol:
Generators automatically implement the iterator protocol, meaning they can be iterated
over using for loops or other iteration mechanisms.
Generator Expressions:
Example:
def count_up_to(n):
i=0
while i <= n:
yield i
i += 1
gen= count_up_to(5)
for num in gen:
print(num)
Output
1
2
3
4
5
Yield vs Return
Yield:
When yield is executed, it pauses the function, returns the current value and retains
the state of the function.
This allows the function to continue from same point when called again, making it
ideal for generating large or complex sequences efficiently.
Return:
Ex
def fun():
return 1 + 2 + 3
res = fun()
print(res)
Output: 6
ITERATORS
An iterator in Python is an object used to traverse through all the elements of a collection
(like lists, tuples, or dictionaries) one element at a time. It follows the iterator protocol,
which involves two key methods:
__next__(): Returns the next value from the sequence. Raises StopIteration when
the sequence ends.
Characteristics
Uniform Looping : Works across data types with the same syntax.
Ex
mystr = "banana"
myit = iter(mystr)
print(next(myit))
print(next(myit))
print(next(myit))
print(next(myit))
print(next(myit))
print(next(myit))
Output
UNIT-II
FILE OPERATIONS
The file is a named location on the disk to store related information, as the file is having
some name and location, it is stored in the hard disk. In Python, file operation is
performed in the following order –
Opening a file.
Read or Write operation.
Closing a file.
To open a file for both reading and writing, we must use the built-in open() function.
The open() function uses two arguments. First is the name of the file and second is the
mode (reading or, writing).
Syntax
A file can be opened with a built-in function called open(). This function takes in the
file’s address and the access_mode and returns a file object. There are different types
of access_modes:
read([size]): It reads the entire file and returns it contents in the form of a string.
Reads at most size bytes from the file. If the size argument is negative or omitted, read
all data until EOF is reached.
Example
f = open(__file__, 'r')
text = f.read(10)
print(text)
f.close()
readline([size]): It reads the first line of the file i.e till a newline character or an EOF
in case of a file having a single line and returns a string. If the size argument is present
and non-negative, it is a maximum byte count and an incomplete line may be returned.
An empty string is returned only when EOF is encountered immediately.
Example
f = open(__file__, 'r')
text = f.readline(20)
print(text)
f.close()
write(string): It writes the contents of string to the file. It has no return value. Due to
buffering, the string may not actually show up in the file until the flush() or close()
method is called.
Example
f = open(__file__, 'w')
line = 'Welcome Geeks\n'
f.write(line)
f.close()
Python supports file handling and allows users to handle files i.e., to read and write files,
along with many other file handling options, to operate on files. For this, python provides
following built–in functions, those are
close()
read()
readline()
write()
writelines()
tell()
seek()
close()
The close() method used to close the currently opened file, after which no more writing
or reading can be done.
Python automatically closes a file when the reference object of a file is reassigned to
another file. It is a good practice to use the close() method to close a file.
Syntax:
Fileobject.close()
read()
The read () method is used to read the content from file. To read a file in Python, we must
open the file in reading mode.
Syntax:
Fileobject.read([size])
readline()
Python facilitates us to read the file line by line by using a function readline(). The
readline() method reads the lines of the file from the beginning, i.e., if we use the
readline() method two times, then we can get the first two lines of the file.
Syntax:
Fileobject.readline()
fileptr.close();
write()
The write () method is used to write the content into file. To write some text to a file, we
need to open the file using the open method with one of the following access modes.
Syntax:
Fileobject.write(content)
writelines()
The writelines () method is used to write multiple lines of content into file. To write some
lines to a file
Syntax:
Fileobject.writelines(list)
File Positions
Methods that set or modify the current position within the file
tell()
The tell() method returns the current file position in a file stream. You can change the
current file position with the seek() method.
Syntax:
Fileobject.tell()
seek()
The seek() method sets and returns the current file position in a file stream.
Syntax:
Fileobject.seek(offset)
In Python, when a file is opened using the open() built-in function, it returns a file
object. This file object possesses several built-in attributes that provide information about
the file and its state. These attributes are distinct from general file system attributes
name: This attribute stores the name of the file, including its path if provided during
opening.
Example
file_object = open("example.txt", "r")
print(file_object.name)
file_object.close()
mode: This attribute indicates the access mode with which the file was opened
Example
file_object = open("example.txt", "w")
print(file_object.mode)
file_object.close()
closed: This is a boolean attribute that indicates whether the file is currently closed
(True) or open (False).
Example
encoding: If the file is opened in text mode, this attribute specifies the encoding used
(e.g., 'utf-8', 'latin-1'). It is None for binary files.
Example
Command Line Arguments provides a convenient way to accept some information at the
command line while running the program. We usually pass these values along with the
name of the Python script
Syntax
Example
C:\Python311>python hello.py
Output
Hello Akhil
FILE SYSTEM
Python offers robust capabilities for interacting with the underlying operating system's
file system through various built-in modules. The primary modules for file system
manipulation in Python are:
OS module:
This module provides a way of using operating system dependent functionality. It
includes functions for interacting with the file system, such as:
Path
manipulation: os.path.join(), os.path.exists(), os.path.isdir(), os.path.isfile(), os.path.sp
lit(), os.path.basename(), os.path.dirname().
Directory
operations: os.mkdir(), os.makedirs(), os.rmdir(), os.removedirs(), os.listdir(), os.getcw
d(), os.chdir().
File operations: os.rename(), os.remove().
Process management: os.system(), os.spawn().
pathlib module:this module provides an object-oriented approach to file system paths,
offering a more modern and user-friendly interface compared to os.path. Key features
include:
Representing paths as Path objects.
Methods for checking file/directory existence (.exists(), .is_file(), .is_dir()),
creating/deleting (.mkdir(), .rmdir(), .unlink()), renaming (.rename()), and joining paths
(/ operator).
shutil module:This module provides higher-level file operations, including:
Copying files and directories: shutil.copy(), shutil.copyfile(), shutil.copytree().
Moving files and directories: shutil.move().
Deleting directory trees: shutil.rmtree().
Example
import os
from pathlib import Path
file_name_os = "my_text_file_os.txt"
with open(file_name_os, "w") as f:
f.write("Hello from os module!\n")
if os.path.exists(file_name_os):
print(f"File '{file_name_os}' exists.")
file_path_pathlib = Path("my_text_file_pathlib.txt")
if file_path_pathlib.is_file():
print(f"File '{file_path_pathlib.name}' exists.")
FILE EXECUTION
Running a Python file, also known as executing a Python script, can be achieved through
various methods depending on your environment.
1. Using the Command Line or Terminal:
This is the most common and fundamental way to run a Python file.
Open a terminal or command prompt:
Navigate to the directory where your Python file (e.g., my_script.py) is saved.
Execute the script:
Type python my_script.py and press Enter.
On some systems, especially Linux, you might need to use python3
my_script.py if python defaults to an older version.
On Windows, py my_script.py can often be used as an alternative to python.
EXCEPTIONS
Python Exception Handling handles errors that occur during the execution of a
program. Exception handling allows to respond to the error, instead of crashing the
running program. It enables you to catch and manage errors, making your code more
robust and user-friendly.
Error: Errors are serious issues that a program should not try to handle. They are
usually problems in the code's logic or configuration and need to be fixed by the
programmer. Examples include syntax errors and memory errors.
Exception: Exceptions are less severe than errors and can be handled by the
program. They occur due to situations like invalid input, missing files or network
issues.
important to handle exceptions carefully and avoid exposing too much information
about your program.
Example(Exception)
n = 10
try:
res = n /
print("Can't be divided by zero!")
Output
Can’t be divided by zero!
Error(Example)
print("Hello world" # Missing closing parenthesis
n = 10
res = n / 0
Output
ERROR!
Traceback (most recent call last):
File "<main.py>", line 1
print("Hello world" # Missing closing parenthesis ^
SyntaxError: '(' was never closed
try:
set(-5)
except ValueError as e:
print(e)
Output
Age cannot be negative.
Exception Objects:
Exceptions are represented by Python objects, which are instances of classes derived
from BaseException.
Handling Exceptions:
Exceptions can be caught and handled using try, except, else, and finally blocks.
The try block contains the code that might raise an exception.
The except block specifies the type of exception to catch and contains the code to
execute if that exception occurs within the try block. Multiple except blocks can be
used to handle different exception types.
The else block (optional) executes if no exception is raised in the try block.
The finally block (optional) always executes, regardless of whether an exception
occurred or was handled. It is commonly used for cleanup operations.
Example
try:
n=0
res = 100 / n
except ZeroDivisionError:
print("You can't divide by zero!")
except ValueError:
print("Enter a valid number!")
else:
print("Result is", res)
finally:
print("Execution complete.")
Output
You can't divide by zero!
Execution complete.
Built-in Exceptions:
Python provides a rich hierarchy of built-in exception classes for common error
conditions, such as ValueError, TypeError, FileNotFoundError, ZeroDivisionError, and
many more.
Custom Exceptions:
Developers can define their own custom exception classes by inheriting from existing
exception classes (typically Exception) to represent specific error conditions in their
applications.
raise statement:
The raise keyword is used to explicitly raise an exception in your code, either a built-in
one or a custom one.
CONTEXT MANAGEMENT
Context management in Python refers to the ability to manage resources within a
controlled block of code, ensuring that resources are properly initialized and cleaned up,
even if exceptions occur. This is primarily achieved through context managers and
the with statement.
Key Concepts:
Context Managers:
These are objects that define a runtime context for a block of code. They implement the
context manager protocol, which involves two special methods:
__enter__(self): This method is called when entering the with statement block. It
typically sets up the resource (e.g., opens a file, acquires a lock) and can return a value
that is bound to the as variable in the with statement.
__exit__(self, exc_type, exc_value, traceback): This method is called when exiting
the with statement block, regardless of whether the block completes normally or an
exception occurs. It's responsible for cleaning up the resource (e.g., closing a file,
releasing a lock). If it returns True, it suppresses any exception that occurred within
the with block.
with Statement:
This statement provides a concise and readable way to utilize context managers.
Syntax :
with expression as variable:
# code block
The expression evaluates to a context manager object. The __enter__ method of this
object is called, and its return value (if any) is assigned to variable. After the code
block finishes, the __exit__ method is called to ensure proper cleanup.
BENEFITS
Resource Management:
Ensures resources like files, network connections, or database connections are properly
opened and closed, preventing resource leaks.
Exception Handling:
Guarantees cleanup even if errors or exceptions occur within the with block.
Code Clarity and Readability:
The with statement provides a clear and concise way to manage resources, making code
easier to understand and maintain.
EXCEPTIONS AS STRINGS
If you need to store the exception message in a string variable or concatenate it with other
strings, you can explicitly convert the exception object to a string using str().
Example
try:
value = int("abc") # This will raise a ValueError
except ValueError as e:
error_message = str(e)
print(f"An error occurred: {error_message}")
Output: An error occurred: invalid literal for int() with base 10: 'abc'
ASSERTIONS
Assertions in Python are statements used to declare that a certain condition must be true
at a specific point in the program's execution. They serve as a debugging tool, helping
developers catch logical errors and incorrect assumptions during development.
Syntax:
assert condition, message
condition: This is a boolean expression that is evaluated.
message : This is a string that will be displayed if the condition evaluates to False.
Behavior:
If condition evaluates to True, the program continues executing normally.
If condition evaluates to False, an AssertionError is raised, and the program halts. The
optional message will be included in the AssertionError traceback.
Purpose and Use Cases:
Debugging:
Assertions are primarily used to catch internal inconsistencies or bugs that indicate a
flaw in the program's logic.
Internal Self-Checks:
They act as internal checks to ensure that the code behaves as expected at various
stages, such as validating function inputs or intermediate results.
Unit Testing:
Assertions are fundamental in unit testing frameworks (like unittest or pytest) to verify
that functions or methods produce the correct output for given inputs.
STANDARD EXCEPTIONS
Python supports various built-in exceptions, the commonly used exceptions are
• NameError: It occurs when a name is not found.i.e attempt to access an undeclared
variable
Example:
a=5
c=a+b
print("Sum =",c)
Output:
Traceback (most recent call last):
File "expdemo.py", line 2, in
c=a+b
NameError: name 'b' is not defined
Output:
Traceback (most recent call last):
File "expdemo.py", line 3, in
print(a/b)
ZeroDivisionError: division by zero
Output:
Enter a number : 23
Enter a number : abc
Traceback (most recent call last):
File "expdemo.py", line 2, in
b=int(input("Enter a number : "))
ValueError: invalid literal for int() with base 10: 'abc'
Output:
Traceback (most recent call last):
File "expdemo.py", line 2, in
print("list item is :",ls[5])
IndexError: list index out of range.
Output:
Traceback (most recent call last):
File "expdemo.py", line 2, in
print("The age is :",dic["age"])
KeyError: 'age'
Output:
Traceback (most recent call last):
File "expdemo.py", line 1, in
fn=open("exam.py")
FileNotFoundError: [IOError] No such file or directory: 'exam.py'
MODULES
A Python module is a file containing Python definitions and statements. A module can
define functions, classes, and variables. A module can also include runnable code.
Grouping related code into a module makes the code easier to understand and use. It
also makes the code logically organized.
Create a Module
To create a module, write the desired code and save that in a file
with .py extension
Example:
def add(x, y):
return (x+y)
def subtract(x, y):
return (x-y)
NAMESPACES
A namespace is basically a system to make sure that all the names in a program
are unique and can be used without any conflict.
A namespace is a system to have a unique name for each and every object in
Python. An object might be a variable or a method. Python itself maintains a
namespace in the form of a Python dictionary.
Real-time example, the role of a namespace is like a surname. One might not find
a single “Kumar” in the class there might be multiple “Kumar” but when you
particularly ask for “N Kumar” or “S Kumar” (with a surname), there will be only
one (time being don’t think of both first name and surname are same for multiple
students).
Types of namespaces
Local Namespace: This namespace includes local names inside a function. This
namespace is created when a function is called, and it only lasts until the function
returns.
Global Namespace: This namespace includes names from various imported
modules that you are using in a project. It is created when the module is included
in the project, and it lasts until the script ends.
Built-in Namespace: This namespace includes built-in functions and built-in
exception names. Like print (), input (), list () and etc.
Example
print("Namespace Example")
#built-in namespace
a=10 #global namespace
def func1():
b=20 #local namespace
print(a+b)
func1()
Output
30
IMPORTING MODULES
We can import the functions, and classes defined in a module to another module using
the import statement in some other Python source file.
When the interpreter encounters an import statement, it imports the module if the
module is present in the search path.
Syntax
import module
Example
import calc
print(calc.add(10, 2))
Output
12
In Python, importing a module allows access to its attributes, which can include
functions, classes, variables, and other objects defined within that module. There are
several ways to import and access module attributes:
1. Importing the entire module:
Syntax
import module_name
2.Accessing attributes using the dot notation: module_name.attribute_name.
Example:
Syntax
import math
print(math.pi)
print(math.sqrt(16))
3. Importing specific attributes from a module:
Syntax
from module_name import attribute1, attribute2
4. Importing all attributes from a module :
Syntax
Syntax
PACKAGES
Python packages are a way to organize and structure code by grouping related modules
into directories. A package is essentially a folder that contains an __init__.py file and
one or more Python files
Components
1. Create a Directory: Make a directory for your package. This will serve as the root
folder.
2. Add Modules: Add Python files (modules) to the directory, each representing
specific functionality.
3. Include __init__.py: Add an __init__.py file (can be empty) to the directory to
mark it as a package.
4. Add Sub packages (Optional): Create subdirectories with their own __init__.py
files for sub packages.
5. Import Modules: Use dot notation to import, e.g., from mypackage.module1
import greet.
Example
math_operations/__init__.py:
UNIT-III
REGULAR EXPRESSIONS
Regular expressions, often referred to as RegEx or regex, are a powerful tool in Python
for pattern matching and manipulating text. They are implemented through the built-
in re module.
KEY CONCEPTS:
Patterns:
Regular expressions define a search pattern using a specialized syntax. This pattern
describes the characteristics of the text you want to find, such as specific character
sequences, character sets, repetitions, or positions within a string.
re Module:
Python's re module provides functions to work with regular expressions. You import it
using import re.
Raw Strings:
It is highly recommended to use raw strings (prefixed with r or R, e.g., r"my\s+pattern")
when defining regex patterns in Python. This prevents backslashes from being
interpreted as escape sequences by Python, ensuring they are passed directly to the
regex engine.
Example
import re
text = "The quick brown fox jumps over the lazy dog."
Python utilizes various special symbols and characters for different functionalities,
including operators, delimiters, escape sequences, and regular expression metacharacters.
1. Operators:
These symbols perform operations on values and variables. Examples include:
Arithmetic: +, -, *, /, // (floor division), % (modulo), ** (exponentiation)
Comparison: ==, !=, <, >, <=, >=
Assignment: =, +=, -=, *= etc.
2. Delimiters:
These characters structure and separate elements within code. Examples include:
Parentheses: (), used for function calls, grouping expressions, and defining tuples.
Square Brackets: [], used for defining lists, accessing elements in sequences, and
slicing.
Curly Braces: {}, used for defining dictionaries and sets.
Comma: ,, used to separate items in lists, tuples, function arguments, etc.
Colon: :, used in if statements, for loops, function definitions, and dictionary key-
value pairs.
Period: ., used for attribute access and floating-point numbers.
3. Escape Characters:
These are special sequences beginning with a backslash (`\`) used to represent characters
that are difficult or impossible to type directly. Common examples include:
\n: Newline
\t: Tab
\r: Carriage return
\\: Literal backslash
\': Literal single quote
\": Literal double quote
In Python, "res" is commonly used as a variable name, typically short for "result," to
store the outcome of a computation or operation. It is not a reserved keyword or built-in
function, but rather a widely adopted naming convention for clarity and conciseness.
Example
final_result = multiply_numbers(5, 4)
print(final_result)
Output: 20
The term "res" can also refer to Regular Expressions (REs, regexes, or regex patterns),
which are a powerful tool for matching text patterns in Python. These are implemented
through the built-in re module.
The re module provides functions for various operations with regular expressions, such
as:
re.search(): Scans through a string looking for the first location where the regular
expression produces a match.
re.findall(): Returns all non-overlapping matches of the pattern in the string, as a list
of strings.
re.sub(): Replaces occurrences of a pattern in a string with a replacement string.
re.split(): Splits a string by the occurrences of a pattern.
MULTITHREADED PROGRAMMING
communication and data sharing between threads compared to separate processes, which
have their own isolated memory spaces.
Key aspects of multithreading
Concurrency within a single process:
Multithreading enables a program to perform multiple tasks seemingly simultaneously
by rapidly switching between threads (context switching), even on a single-core CPU.
Shared memory space:
Threads within the same process share resources like memory, global variables, and
open files, facilitating data exchange.
Threading module:
Python's built-in threading module provides the tools to create, manage, and
synchronize threads.
I/O-bound tasks:
Multithreading is particularly beneficial for I/O-bound operations (e.g., network
requests, file I/O, database queries) where the program spends a significant amount of
time waiting for external resources. During these waiting periods, other threads can
execute, improving overall responsiveness.
Global Interpreter Lock (GIL):
Python's CPython implementation includes a Global Interpreter Lock (GIL), which
limits true parallel execution for CPU-bound tasks. The GIL ensures that only one
thread can execute Python bytecode at a time, even on multi-core processors. This
means multithreading may not provide significant performance gains for
computationally intensive tasks in CPython. For such tasks,
the multiprocessing module, which creates separate processes, is often more suitable.
In Python, both threads and processes are mechanisms for achieving concurrency,
allowing multiple tasks to seemingly run at the same time. However, they differ
significantly in their implementation and suitability for various tasks.
PROCESSES:
Independent Programs:
A process is an independent instance of a running program, with its own dedicated
memory space, resources, and execution environment.
True Parallelism:
Processes can achieve true parallelism on multi-core CPUs because each process runs
independently and is not subject to the Global Interpreter Lock (GIL).
Higher Overhead:
Creating and managing processes involves more overhead (memory and time)
compared to threads due to their independent nature.
Inter-Process Communication (IPC):
Communication between processes requires explicit mechanisms like pipes, queues, or
shared memory, as they do not share memory directly.
Best for CPU-bound tasks:
Ideal for computationally intensive tasks that benefit from parallel execution on
multiple cpu cores, as they bypass the gil.
THREADS:
Units within a Process:
Threads are lightweight units of execution within a single process, sharing the same
memory space and resources.
Concurrency, not True Parallelism (due to GIL):
In CPython (the standard Python interpreter), a Global Interpreter Lock (GIL) ensures
that only one thread can execute Python bytecode at a time, even on multi-core
systems. This means threads achieve concurrency (tasks appear to run simultaneously
by switching quickly), but not true parallelism for CPU-bound operations.
Lower Overhead:
Threads are "lighter" than processes, requiring less overhead for creation and context
switching.
Shared Memory:
Threads within the same process can easily share data and communicate through shared
memory, but this requires careful synchronization (e.g., using locks) to prevent race
conditions.
Best for I/O-bound tasks:
Suitable for tasks that involve waiting for external resources (like network requests or
file I/O), as the GIL is released during these waiting periods, allowing other threads to
run.
As a general rule, an interpreter that uses GIL will see only one thread to execute at a
time, even if it runs on a multi-core processor, although some implementations provide
for CPU intensive code to release the GIL, allowing multiple threads to use multiple
cores. Some popular interpreters that have a GIL are CPython and Ruby MRI.
Advantages
Example
from threading import Lock
INSTRUCTION_TABLE = { ... }
def execute(bytecode: list) -> None:
"""Execute bytecode."""
lock = Lock()
for (opcode, args) in bytecode:
lock.acquire()
INSTRUCTION_TABLE[opcode](args)
lock.release()
Threads are particularly useful for tasks that involve waiting for external resources
(I/O-bound tasks), such as network requests, file operations, or database queries, as they
allow the program to perform other operations while waiting.
THREADING MODULE
The threading module offers a more robust and user-friendly way to manage threads
compared to the older, lower-level _thread module. Key features and components
include:
Thread class:
This is the primary class for creating and managing individual threads. You can define a
custom class that inherits from threading.Thread and overrides its run() method, or you
can pass a target function to the Thread constructor.
Synchronization primitives:
The module provides various tools to manage concurrent access to shared resources and
prevent race conditions, such as:
Lock: A basic lock that ensures only one thread can acquire it at a time, protecting
critical sections of code.
RLock (Reentrant Lock): Similar to Lock, but allows the same thread to acquire it
multiple times.
Semaphore: A counter-based lock that limits the number of threads that can access
a resource concurrently.
Event: A simple signaling mechanism where one thread can signal an event, and
other threads can wait for that event to be set.
Condition: Allows threads to wait for specific conditions to be met before
proceeding.
Example
import threading
import time
def worker_function(name, delay):
"""A function to be executed by a thread."""
print(f"Thread {name}: Starting...")
time.sleep(delay)
Python provides various options for developing graphical user interfaces (GUIs).
Some of them are
Tkinter- Tkinter is the python interface to the TK GUI toolkit shipped with python
PyGTK- PyGTK is a set of wrappers written in python and c for GTK + GUI library
Jython- Jython is a python port of java,which gives python scripts seamless acess to the
java class libraries on local machine
Tkinter is Python’s built-in library for creating graphical user interfaces (GUIs). It
acts as a lightweight wrapper around Tcl/Tk GUI toolkit, offering Python developers a
simple and intuitive way to build desktop applications. It supports layout management,
event handling and customization, making it ideal for rapid GUI development in
Python.
Features
1. Provides a built-in and easy-to-use way to create GUI (Graphical User Interface)
applications in Python.
2. Offers various widgets like buttons, labels, text boxes and menus to build
interactive apps.
3. Eliminates the need for external GUI frameworks tkinter comes bundled with
Python.
4. Useful for building desktop applications like calculators, form apps and
dashboards.
5. Supports event-driven programming, making it suitable for responsive user
interfaces.
1. Import the tkinter module: Import the tkinter module, which is necessary for
creating the GUI components.
2. Create the main window (container): Initialize the main application window
using the Tk() class.
3. Set Window Properties: We can set properties like the title and size of the
window.
4. Add widgets to the main window: We can add any number of widgets like
buttons, labels, entry fields, etc., to the main window to design the interface.
5. Pack Widgets: Use geometry managers like pack(), grid() or place() to arrange the
widgets within the window.
6. Apply event triggers to the widgets: We can attach event triggers to the widgets
to define how they respond to user interactions.
There are two main methods used which user needs to remember while creating the
Python application with GUI. These methods are:
1. Tk()
To create a main window in Tkinter, we use the Tk() class.
Syntax:
root = tk.Tk(screenName=None, baseName=None, className='Tk', useTk=1)
Parameter:
screenName: This parameter is used to specify the display name.
baseName: This parameter can be used to set the base name of the application.
className: We can change the name of the window by setting this parameter to
the desired name.
useTk: This parameter indicates whether to use Tk or not.
2. mainloop()
The mainloop() method is used to run application once it is ready. It is an infinite loop
that keeps application running, waits for events to occur (such as button clicks) and
processes these events as long as window is not closed.
Example:
This code initializes a basic GUI window using Tkinter. The tkinter.Tk() function
creates main application window, mainloop() method starts event loop, which keeps
the window running and responsive to user interactions.
import tkinter
m = tkinter.Tk()
'''
widgets are added here
'''
m.mainloop()
Output
Frameworks:
Python boasts a rich ecosystem of web frameworks that streamline development.
Django: A high-level, "batteries-included" framework known for its rapid
development capabilities and emphasis on convention over configuration. It provides
built-in features for user authentication, administration, forms, and more.
Flask: A lightweight micro-framework offering more flexibility and control. It is
suitable for smaller projects or when a developer prefers to choose individual
components.
Other frameworks: CherryPy, Pyramid, Web2py, and Bottle are also available,
each with its own strengths and use cases.
Server-Side Development:
Advantages:
Readability and Simplicity: Python's clear syntax makes it easy to learn and
write code, leading to faster development.
Extensive Libraries: A vast collection of libraries and packages are available for
various tasks, from data analysis to machine learning, which can be integrated into web
applications.
Scalability and Robustness: Frameworks like Django provide features for
building scalable and secure applications.
Community Support: Python has a large and active community, offering
extensive documentation and support.
Example
import webbrowser
Example
url = "http://olympus.realpython.org/profiles/aphrodite"
page = urlopen(url)
html_bytes = page.read()
html = html_bytes.decode("utf-8")
print(html)
Creating a simple web client in Python can be accomplished using the built-
in socket module for low-level network communication or the more user-
friendly requests library for handling HTTP requests.
# Send data
message = "Hello from the client!"
client_socket.sendall(message.encode())
# Receive data
data = client_socket.recv(1024)
print(f"Received from server: {data.decode()}")
# Close the connection
client_socket.close()
Advanced web clients in Python extend beyond basic document downloading to perform
complex interactions with web resources. These clients are commonly used for tasks such
as:
Web Scraping and Crawling:
Automatically extracting data from websites, indexing content for search engines, or
building local archives.
Automated Testing and Browser Automation:
Simulating user interactions for testing web applications or automating repetitive tasks
within a browser environment.
Building Custom Applications:
Creating specialized applications that communicate with web APIs, integrate with
online services, or provide offline browsing capabilities.
Several Python libraries facilitate the development of advanced web clients:
Requests: A popular and user-friendly library for making HTTP requests. It
simplifies common tasks like handling sessions, cookies, and authentication.
Example
import requests
response = requests.get('https://example.com')
print(response.text)
Example
import aiohttp
import asyncio
if __name__ == '__main__':
asyncio.run(main())
Scrapy:
A powerful and comprehensive framework specifically designed for web crawling and
data extraction. It provides a high-level structure for building scalable and efficient
crawlers.
Selenium:
A library for browser automation, allowing you to control a web browser
programmatically. It is ideal for interacting with dynamic web pages, executing
JavaScript, and simulating user behavior.
Example
Beautiful Soup: A library for parsing HTML and XML documents, often used in
conjunction with HTTP clients like Requests to extract specific data from web pages
Example
response = requests.get('https://example.com')
soup = BeautifulSoup(response.text, 'html.parser')
print(soup.title.string)
The Common Gateway Interface (CGI) is a standard method that enables web servers to
interact with external applications, allowing them to process client data and generate
dynamic content. Essentially, CGI acts as a bridge between the web server and these
applications, facilitating the exchange of information.
When a client submits data (e.g., through an HTML form), the web server receives this
request and, if configured for CGI, passes the relevant information to a designated CGI
program. This program, written in languages like Python, Perl, C, or Java, processes the
client's input, performs necessary actions (like querying a database or performing
calculations), and then generates dynamic content, typically in HTML format. The web
server then receives this generated content from the CGI program and sends it back to the
client's browser as a response.
In essence, CGI allows web servers to move beyond serving static files and provide
interactive experiences where client input can trigger server-side processing and result in
customized, dynamic web pages.
Example
print("Content-type: text/html\n\n")
print("<html>")
print("<head>")
print("<title>My CGI Application</title>")
print("</head>")
print("<body>")
form = cgi.FieldStorage()
name = form.getvalue("name")
if name:
print(f"<h1>Hello, {name}!</h1>")
else:
print("<h1>Please provide your name.</h1>")
print("</body>")
print("</html>")
ADVANCED CGI
While the cgi module in Python's standard library provided support for Common
Gateway Interface (CGI) scripting, it has been deprecated since Python 3.11 and removed
in Python 3.13. This means that using the cgi module for advanced CGI programming is
no longer recommended for modern Python development.
The removal of the cgi module reflects a shift in web development practices, moving
away from traditional CGI scripts towards more robust and feature-rich web
frameworks. These frameworks provide a more structured and efficient way to build web
applications, including handling requests, managing sessions, interacting with databases,
and generating dynamic content.
For advanced web development in Python, including tasks that might have previously
been handled by advanced CGI techniques (like handling complex forms, file uploads, or
managing cookies and sessions), modern web frameworks are the recommended
approach.
Examples of such frameworks include:
Django:
A high-level web framework that encourages rapid development and clean, pragmatic
design. It includes a comprehensive ORM, an administrative interface, and a templating
system.
Flask:
A microframework for Python that is lightweight and flexible, allowing developers to
choose their own tools and libraries.
FastAPI:
A modern, fast (high-performance) web framework for building APIs with Python 3.7+
based on standard Python type hints.
These frameworks offer built-in functionalities and extensions that simplify the
development of complex web applications, providing a more secure, scalable, and
maintainable alternative to traditional CGI scripting. If a project requires using
the cgi module specifically, a fork of the module is available on PyPI under the
name legacy-cgi. However, this is not supported by the core Python team and should be
used with caution, primarily for maintaining older codebases.
WEB(HTTP)SERVERS
Python provides several ways to create an HTTP web server, ranging from simple built-in
modules for serving static files to more robust frameworks for building dynamic web
applications.
1. Simple Static File Server (using http.server):
For serving static files from a directory, Python's built-in http.server module offers a
quick solution.
Code
python3 -m http.server 8000
This command starts an HTTP server on port 8000, serving the contents of the current
directory. You can then access the files by navigating to http://localhost:8000/ in your
web browser.
2. Custom HTTP Server (using http.server and socketserver):
For more control over request handling, you can create a custom server
using http.server.BaseHTTPRequestHandler and socketserver.TCPServer.
Code
import http.server
import socketserver
PORT = 8000
class MyHandler(http.server.BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(b"<h1>Hello from Python!</h1>")
with socketserver.TCPServer(("", PORT), MyHandler) as httpd:
print(f"Serving at port {PORT}")
httpd.serve_forever()
This example creates a server that responds to all GET requests with a simple "Hello
from Python!" message. You can customize the do_GET, do_POST, etc., methods to
handle different request types and serve dynamic content.
DATABASE PROGRAMMING
Database programming in Python involves using Python to interact with various types of
databases, including relational databases like MySQL, PostgreSQL, and SQLite, as well
as non-relational databases such as MongoDB and Redis.
Key aspects of database programming in Python:
Database Drivers/Connectors:
Python requires specific libraries or drivers to connect to different database
systems. Examples include mysql-connector-python for MySQL, psycopg2 for
PostgreSQL, sqlite3 (built-in) for SQLite, and pymongo for MongoDB.
Connecting to the Database:
The first step is to establish a connection to the database server. This typically involves
providing connection details like host, username, password, and the database name.
Code
import mysql.connector
mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
Code
mycursor = mydb.cursor()
Code
Code
Code
mydb.commit()
Closing the Connection: After completing database operations, the connection and
cursor objects should be closed to release resources.
Code
mycursor.close()
mydb.close()
Standard Exceptions:
The DB-API defines a set of standard exceptions
(e.g., Error, Warning, InterfaceError, DatabaseError) that database drivers should raise
in response to specific database-related issues, ensuring consistent error handling.
Module Contents:
The specification outlines required module-level attributes and functions that database
drivers must implement to conform to the DB-API standard.
By adhering to the DB-API, Python database modules (like sqlite3, psycopg2 for
PostgreSQL, mysql-connector-python for MySQL) offer a familiar and predictable way
to interact with databases, simplifying development and promoting code portability.
Mapping:
ORMs map Python classes to database tables and instances of those classes to rows
within those tables. Attributes of the Python objects correspond to columns in the
database.
Abstraction:
They translate object-oriented operations (e.g., creating an object, modifying an object's
attribute, querying for objects) into the appropriate SQL statements, which are then
executed against the database.
Simplification:
This abstraction simplifies database interactions, making it more intuitive for Python
developers to work with data, especially those less familiar with SQL.
Key Benefits of Using ORMs:
Increased Productivity:
Developers can work with familiar Python objects and methods, reducing the need to
write and manage complex SQL queries.
Reduced Boilerplate Code:
ORMs often handle common database tasks like connection management, data type
conversions, and relationship mapping, reducing the amount of manual code required.
Database Agnosticism:
Many ORMs support multiple database systems (e.g., PostgreSQL, MySQL, SQLite),
allowing for easier switching between databases with minimal code changes.
Improved Maintainability:
By abstracting database interactions, ORMs can make code more readable and easier to
maintain.
Popular Python ORMs:
SQLAlchemy:
A powerful and flexible ORM that provides both a SQL Expression Language and an
ORM component. It is highly configurable and suitable for complex applications.
Django ORM:
The built-in ORM for the Django web framework. It is tightly integrated with Django's
features and provides a convenient way to manage database interactions within Django
projects.
Peewee:
A lightweight and expressive ORM designed for simplicity and ease of use, particularly
for smaller projects.
PonyORM:
An ORM that uses Python's generator expressions for defining queries, aiming for a
more Pythonic and intuitive query syntax.
Tortoise ORM:
An asynchronous ORM designed for use with asyncio applications, commonly used in
conjunction with asynchronous web frameworks like FastAPI.