Ex:1
Python Lab Program: Function Types and Scopes Analysis
Aim:
To analyze the scopes of different types of functions in Python, including global, local, and
nonlocal scopes, using print statements and debugging tools like pdb.
Algorithm:
1. Step 1: Understand Function Scopes:
o Global Scope: Variables defined outside any function or class. Accessible
from anywhere in the code.
o Local Scope: Variables defined within a function. Accessible only within that
function.
o Nonlocal Scope: Variables used in nested functions. They are neither local nor
global but belong to the nearest enclosing function.
2. Step 2: Setup the Environment:
o Write a Python script that demonstrates the use of global, local, and nonlocal
variables.
o Use print statements to trace the values of variables in different scopes.
3. Step 3: Define a Global Variable:
o Define a global variable outside all functions.
o Write a function that accesses and modifies this global variable using the
global keyword.
4. Step 4: Create a Function with Local Scope:
o Inside the function, define a local variable.
o Use print statements to show that this variable is not accessible outside the
function.
5. Step 5: Create a Nested Function for Nonlocal Scope:
o Define a function inside another function.
o Inside the inner function, use the nonlocal keyword to modify a variable from
the enclosing function’s scope.
o Use print statements to demonstrate how the variable's value changes.
6. Step 6: Debugging with pdb:
o Use Python's built-in debugger pdb to step through the code and inspect the
scope of variables.
o Set breakpoints at key points in the code to analyze the flow and scope.
7. Step 7: Run and Analyze the Program:
o Run the program and analyze the output from the print statements and the pdb
debugger.
8. Step 8: Document the Results:
o Document the behavior of global, local, and nonlocal variables as observed in
the program.
# Global variable
global_var = "I am global!"
def outer_function():
# Local variable in the outer function
outer_var = "I am local to outer_function!"
def inner_function():
# Accessing nonlocal variable
nonlocal outer_var
outer_var = "I am modified by inner_function!"
print("Inside inner_function:", outer_var)
print("Before calling inner_function:", outer_var)
inner_function()
print("After calling inner_function:", outer_var)
def modify_global():
global global_var
global_var = "I am modified globally!"
print("Before modify_global call:", global_var)
modify_global()
print("After modify_global call:", global_var)
outer_function()
# Using pdb for debugging (optional)
import pdb; pdb.set_trace()
# Global variable access outside any function
print("Outside all functions:", global_var)
output:
Before modify_global call: I am global!
After modify_global call: I am modified globally!
Before calling inner_function: I am local to outer_function!
Inside inner_function: I am modified by inner_function!
After calling inner_function: I am modified by inner_function!
Ex:2
Python Lab Program: Argument Passing Techniques Comparison
Aim:
To compare different argument passing techniques in Python functions, including positional
arguments, keyword arguments, default arguments, and variable-length arguments, through
experimental evaluation.
Algorithm:
1. Step 1: Understand Argument Passing Techniques:
o Positional Arguments: Arguments passed to a function based on their
position.
o Keyword Arguments: Arguments passed to a function by explicitly naming
each one.
o Default Arguments: Arguments that assume a default value if not provided by
the caller.
o Variable-length Arguments: Allows a function to accept any number of
arguments using *args for non-keyword and **kwargs for keyword arguments.
2. Step 2: Setup the Environment:
o Write a Python script that includes multiple functions demonstrating each type
of argument passing.
o Use print statements to display the behavior of each function.
3. Step 3: Define Functions for Each Technique:
o Create a function that uses positional arguments.
o Create a function that uses keyword arguments.
o Create a function that uses default arguments.
o Create a function that uses variable-length arguments.
4. Step 4: Compare Argument Passing Techniques:
o Call each function with different sets of arguments.
o Compare how the functions handle the arguments and how the outputs differ
based on the type of argument passing.
5. Step 5: Document the Results:
o Document the behavior of each function and the differences between argument
passing techniques.
6. Step 6: Run and Analyze the Program:
o Run the program and analyze the output for each argument passing technique.
# Positional Arguments
def positional_example(a, b):
print("Positional Example - a:", a, "b:", b)
# Keyword Arguments
def keyword_example(a, b):
print("Keyword Example - a:", a, "b:", b)
# Default Arguments
def default_example(a, b=10):
print("Default Example - a:", a, "b:", b)
# Variable-Length Arguments (*args for non-keyword, **kwargs for keyword)
def variable_length_example(*args, **kwargs):
print("Variable-Length Example - args:", args, "kwargs:", kwargs)
# Experimenting with Positional Arguments
print("Calling positional_example(1, 2):")
positional_example(1, 2)
# Experimenting with Keyword Arguments
print("\nCalling keyword_example(a=1, b=2):")
keyword_example(a=1, b=2)
print("Calling keyword_example(b=2, a=1):")
keyword_example(b=2, a=1)
# Experimenting with Default Arguments
print("\nCalling default_example(5):")
default_example(5)
print("Calling default_example(5, 15):")
default_example(5, 15)
# Experimenting with Variable-Length Arguments
print("\nCalling variable_length_example(1, 2, 3, x=10, y=20):")
variable_length_example(1, 2, 3, x=10, y=20)
print("Calling variable_length_example(x=10, y=20):")
variable_length_example(x=10, y=20)
output:
Calling positional_example(1, 2):
Positional Example - a: 1 b: 2
Calling keyword_example(a=1, b=2):
Keyword Example - a: 1 b: 2
Calling keyword_example(b=2, a=1):
Keyword Example - a: 1 b: 2
Calling default_example(5):
Default Example - a: 5 b: 10
Calling default_example(5, 15):
Default Example - a: 5 b: 15
Calling variable_length_example(1, 2, 3, x=10, y=20):
Variable-Length Example - args: (1, 2, 3) kwargs: {'x': 10, 'y': 20}
Calling variable_length_example(x=10, y=20):
Variable-Length Example - args: () kwargs: {'x': 10, 'y': 20}
=== Code Execution Successful ===
Ex:3
Python Lab Program: Demonstrating Unpacking of Function Arguments Using *args
and **kwargs
Aim:
To create experiments that demonstrate the unpacking of function arguments in Python using
*args (non-keyword arguments) and **kwargs (keyword arguments).
Algorithm:
1. Step 1: Understand Argument Unpacking:
o *args: Allows a function to accept a variable number of positional arguments,
which are packed into a tuple.
o **kwargs: Allows a function to accept a variable number of keyword
arguments, which are packed into a dictionary.
2. Step 2: Setup the Environment:
o Write a Python script that includes multiple functions demonstrating
unpacking using *args and **kwargs.
o Use print statements to display how the arguments are unpacked inside the
function.
3. Step 3: Create Functions to Demonstrate *args:
o Define a function that takes *args as a parameter.
o Inside the function, unpack the arguments and demonstrate different ways to
use them.
4. Step 4: Create Functions to Demonstrate **kwargs:
o Define a function that takes **kwargs as a parameter.
o Inside the function, unpack the keyword arguments and demonstrate how they
can be accessed and used.
5. Step 5: Combine *args and **kwargs:
o Create a function that accepts both *args and **kwargs.
o Demonstrate how the function handles a mixture of positional and keyword
arguments.
6. Step 6: Run and Analyze the Program:
o Run the program and analyze how *args and **kwargs are unpacked and
utilized in each experiment.
# Function to demonstrate *args
def demo_args(*args):
print("Received *args as a tuple:", args)
for i, arg in enumerate(args):
print(f"Argument {i}: {arg}")
# Function to demonstrate **kwargs
def demo_kwargs(**kwargs):
print("Received **kwargs as a dictionary:", kwargs)
for key, value in kwargs.items():
print(f"{key}: {value}")
# Function to demonstrate combined use of *args and **kwargs
def demo_args_kwargs(*args, **kwargs):
print("Received *args:", args)
print("Received **kwargs:", kwargs)
# Experimenting with *args
print("Calling demo_args(1, 2, 3, 4):")
demo_args(1, 2, 3, 4)
# Experimenting with **kwargs
print("\nCalling demo_kwargs(a=10, b=20, c=30):")
demo_kwargs(a=10, b=20, c=30)
# Experimenting with combined *args and **kwargs
print("\nCalling demo_args_kwargs(1, 2, 3, x=10, y=20):")
demo_args_kwargs(1, 2, 3, x=10, y=20)
# Unpacking a list and a dictionary into *args and **kwargs
args_list = [1, 2, 3, 4]
kwargs_dict = {'a': 10, 'b': 20, 'c': 30}
print("\nCalling demo_args_kwargs with unpacked list and dictionary:")
demo_args_kwargs(*args_list, **kwargs_dict)
output:
alling demo_args(1, 2, 3, 4):
Received *args as a tuple: (1, 2, 3, 4)
Argument 0: 1
Argument 1: 2
Argument 2: 3
Argument 3: 4
Calling demo_kwargs(a=10, b=20, c=30):
Received **kwargs as a dictionary: {'a': 10, 'b': 20, 'c': 30}
a: 10
b: 20
c: 30
Calling demo_args_kwargs(1, 2, 3, x=10, y=20):
Received *args: (1, 2, 3)
Received **kwargs: {'x': 10, 'y': 20}
Calling demo_args_kwargs with unpacked list and dictionary:
Received *args: (1, 2, 3, 4)
Received **kwargs: {'a': 10, 'b': 20, 'c': 30}
=== Code Execution Successful ===
Ex:5
Python Lab Program: Exploring Assertion Testing in Python
Aim:
To explore the usage and effectiveness of assertions in debugging Python code by designing
experiments with custom assertions.
Algorithm:
1. Step 1: Understand Assertions:
o An assertion is a statement that checks whether a condition is true at a specific
point in the program.
o If the condition is False, an AssertionError is raised, halting the program.
o Assertions are typically used to catch bugs during development and are not
meant to handle runtime errors in production.
2. Step 2: Setup the Environment:
o Write a Python script with multiple functions, each containing custom
assertions to validate different conditions.
o These functions will include logical checks where the correctness of the
conditions can be asserted.
3. Step 3: Design Custom Assertions:
o Design assertions to check the validity of inputs, boundary conditions, and
logical flows within functions.
o Create assertions for various scenarios like checking list lengths, value ranges,
string contents, etc.
4. Step 4: Test the Assertions:
o Call the functions with both valid and invalid inputs to trigger the assertions.
o Observe how the assertions help in identifying logical errors early in the
program.
5. Step 5: Document the Results:
o Document the scenarios where assertions catch errors and how they contribute
to debugging.
import math
import time
import numpy as np
# Experiment 1: Basic Assertion to Validate Function Inputs
def safe_sqrt(x):
assert x >= 0, f"Expected non-negative number, got {x}"
return math.sqrt(x)
# Test Experiment 1
print("Experiment 1: Basic Assertion to Validate Function Inputs")
try:
print(safe_sqrt(9)) # Expected: 3.0
print(safe_sqrt(-4)) # Should raise an assertion error
except AssertionError as e:
print(f"AssertionError: {e}")
print()
# Experiment 2: Custom Assertion for Complex Data Validation
def process_students(students):
for student in students:
assert 'name' in student and 'age' in student and 'grade' in student, \
f"Missing keys in student data: {student}"
# Process student data
print(f"Processing {student['name']}")
# Test Experiment 2
print("Experiment 2: Custom Assertion for Complex Data Validation")
students_data = [
{'name': 'Alice', 'age': 20, 'grade': 'A'},
{'name': 'Bob', 'grade': 'B'}, # Missing 'age'
try:
process_students(students_data) # Should raise an assertion error for the second student
except AssertionError as e:
print(f"AssertionError: {e}")
print()
# Experiment 3: Assertions to Validate Post-Conditions
def sort_list(numbers):
sorted_numbers = sorted(numbers)
assert all(sorted_numbers[i] <= sorted_numbers[i+1] for i in range(len(sorted_numbers)-
1)), \
"List is not sorted"
return sorted_numbers
# Test Experiment 3
print("Experiment 3: Assertions to Validate Post-Conditions")
try:
print(sort_list([3, 1, 2])) # Expected: [1, 2, 3]
print(sort_list([3, 2, 1])) # Should pass as it's sorted internally
except AssertionError as e:
print(f"AssertionError: {e}")
print()
# Experiment 4: Custom Assertions for Unit Testing
def factorial(n):
assert n >= 0, "Factorial is not defined for negative numbers"
if n == 0 or n == 1:
return 1
return n * factorial(n-1)
def test_factorial():
assert factorial(0) == 1, "Failed on factorial(0)"
assert factorial(1) == 1, "Failed on factorial(1)"
assert factorial(5) == 120, "Failed on factorial(5)"
assert factorial(7) == 5040, "Failed on factorial(7)"
# Test for an edge case with invalid input
try:
factorial(-1) # Should raise an assertion error
except AssertionError as e:
print(f"AssertionError in test_factorial: {e}")
# Test Experiment 4
print("Experiment 4: Custom Assertions for Unit Testing")
test_factorial()
print()
# Experiment 5: Assertions in Performance-Critical Code
def matrix_multiply(A, B):
assert len(A[0]) == len(B), "Incompatible matrix dimensions"
result = np.dot(A, B)
return result
# Test Experiment 5
print("Experiment 5: Assertions in Performance-Critical Code")
# Create large matrices
A = np.random.rand(1000, 1000)
B = np.random.rand(1000, 1000)
# Measure performance with assertions
start_time = time.time()
try:
result_with_assertions = matrix_multiply(A, B)
print(f"Time with assertions: {time.time() - start_time:.4f} seconds")
except AssertionError as e:
print(f"AssertionError: {e}")
# Measure performance without assertions
start_time = time.time()
result_without_assertions = np.dot(A, B) # Directly multiply without assertions
print(f"Time without assertions: {time.time() - start_time:.4f} seconds")
output:
xperiment 1: Basic Assertion to Validate Function Inputs
3.0
AssertionError: Expected non-negative number, got -4
Experiment 2: Custom Assertion for Complex Data Validation
Processing Alice
AssertionError: Missing keys in student data: {'name': 'Bob', 'grade': 'B'}
Experiment 3: Assertions to Validate Post-Conditions
[1, 2, 3]
[1, 2, 3]
Experiment 4: Custom Assertions for Unit Testing
AssertionError in test_factorial: Factorial is not defined for negative numbers
Experiment 5: Assertions in Performance-Critical Code
Time with assertions: 0.0140 seconds
Time without assertions: 0.0188 second
Ex:6
Python Lab Program: Recursion Performance Analysis
Aim:
To measure and compare the performance of recursive functions with their iterative
counterparts for various problem sets, such as calculating the factorial, Fibonacci sequence,
and sum of an array.
Algorithm:
1. Step 1: Understand Recursion and Iteration:
o Recursion: A function calls itself to solve a smaller instance of the problem
until a base case is reached.
o Iteration: A loop is used to solve the problem by repeatedly executing a set of
instructions.
2. Step 2: Select Problem Sets:
o Choose problems that can be solved using both recursive and iterative
methods, such as:
Calculating the factorial of a number.
Generating the Fibonacci sequence.
Summing the elements of an array.
3. Step 3: Implement Recursive Functions:
o Write Python functions that solve each problem using recursion.
4. Step 4: Implement Iterative Functions:
o Write Python functions that solve the same problems using iteration.
5. Step 5: Measure Performance:
o Use Python’s time module to measure the execution time of both recursive and
iterative functions.
o Run each function multiple times to obtain average execution times.
6. Step 6: Compare Results:
o Compare the execution times of recursive and iterative solutions.
o Analyze the scenarios where recursion is less or more efficient than iteration.
7. Step 7: Document Findings:
o Summarize the results, highlighting the performance differences and
discussing the trade-offs between recursion and iteration.
import time
# Recursive function to calculate factorial
def factorial_recursive(n):
if n == 0 or n == 1:
return 1
else:
return n * factorial_recursive(n - 1)
# Iterative function to calculate factorial
def factorial_iterative(n):
result = 1
for i in range(2, n + 1):
result *= i
return result
# Recursive function to calculate nth Fibonacci number
def fibonacci_recursive(n):
if n <= 1:
return n
else:
return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2)
# Iterative function to calculate nth Fibonacci number
def fibonacci_iterative(n):
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return a
# Recursive function to sum elements of an array
def sum_array_recursive(arr):
if len(arr) == 0:
return 0
else:
return arr[0] + sum_array_recursive(arr[1:])
# Iterative function to sum elements of an array
def sum_array_iterative(arr):
total = 0
for num in arr:
total += num
return total
# Function to measure performance
def measure_time(func, *args):
start = time.time()
result = func(*args)
end = time.time()
return result, end - start
# Test data
n = 30
arr = list(range(1, 1001))
# Measure and compare factorial
print("Factorial of", n)
result, time_recursive = measure_time(factorial_recursive, n)
print("Recursive:", result, "Time:", time_recursive)
result, time_iterative = measure_time(factorial_iterative, n)
print("Iterative:", result, "Time:", time_iterative)
# Measure and compare Fibonacci
print("\nFibonacci number at position", n)
result, time_recursive = measure_time(fibonacci_recursive, n)
print("Recursive:", result, "Time:", time_recursive)
result, time_iterative = measure_time(fibonacci_iterative, n)
print("Iterative:", result, "Time:", time_iterative)
# Measure and compare sum of array
print("\nSum of array")
result, time_recursive = measure_time(sum_array_recursive, arr)
print("Recursive:", result, "Time:", time_recursive)
result, time_iterative = measure_time(sum_array_iterative, arr)
print("Iterative:", result, "Time:", time_iterative)
Ex:7 Inheritance
Aim:
The aim of an inheritance program in Python is to illustrate the concept of inheritance, where
a derived class inherits attributes and methods from a base class, allowing for code reuse and
extension. This concept enables creating a hierarchy of classes where derived classes can
override or extend the behavior of base classes.
Algorithm for an Inheritance Program:
1. Define the Base Class:
o Create a base class that contains common attributes and methods that will be
inherited by derived classes.
o Implement an __init__ method to initialize the base class attributes.
o Define methods that can be overridden or used as-is by derived classes.
2. Define Derived Classes:
o Create derived classes that inherit from the base class.
o Use the super() function in the __init__ method of the derived classes to
initialize attributes from the base class.
o Override base class methods to provide specific implementations relevant to
the derived class.
o Add additional attributes or methods specific to the derived classes if needed.
3. Create Instances:
o Instantiate objects of the base class and derived classes to demonstrate how
inheritance works.
4. Demonstrate Inheritance:
o Call methods on instances of the base and derived classes to show inherited
and overridden behavior.
o Use functions like isinstance() to check the type of instances and confirm
inheritance.
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "Some generic animal sound"
def describe(self):
return f"This is a {self.name}."
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name) # Call the __init__ method of the base class
self.breed = breed
def speak(self):
return "Woof!"
def describe(self):
return f"This is a {self.breed} dog named {self.name}."
class Cat(Animal):
def __init__(self, name, color):
super().__init__(name) # Call the __init__ method of the base class
self.color = color
def speak(self):
return "Meow!"
def describe(self):
return f"This is a {self.color} cat named {self.name}."
# Create instances of each class
animal = Animal("generic animal")
dog = Dog("Buddy", "Golden Retriever")
cat = Cat("Whiskers", "black")
# Demonstrate behavior of inherited methods and attributes
print(animal.describe()) # This is a generic animal.
print(animal.speak()) # Some generic animal sound
print(dog.describe()) # This is a Golden Retriever dog named Buddy.
print(dog.speak()) # Woof!
print(cat.describe()) # This is a black cat named Whiskers.
print(cat.speak()) # Meow!
# Show that Dog and Cat instances can access methods from Animal
print(isinstance(dog, Animal)) # True
print(isinstance(cat, Animal)) # True
# Show that methods in derived classes override base class methods
print(dog.speak()) # Woof!
print(cat.speak()) # Meow!
Outout:
This is a generic animal.
Some generic animal sound
This is a Golden Retriever dog named Buddy.
Woof!
This is a black cat named Whiskers.
Meow!
True
True
Woof!
Meow!
Ex:8 File handling
Aim:
The aim of file handling in Python is to enable programs to perform operations on files, such
as creating, reading, writing, and deleting files. This allows programs to manage persistent
data storage and retrieve information as needed. File handling is crucial for applications that
need to store data permanently or share data between different runs of the program.
Algorithm for File Handling:
1. Open a File:
o Use the open() function to access a file.
o Specify the file name and mode ('r', 'w', 'a', 'b', etc.).
2. Perform Operations on the File:
o Reading:
Use read(), readline(), or readlines() methods to read the content.
o Writing:
Use write() or writelines() methods to write content to the file.
o Appending:
Use 'a' mode and write() or writelines() to add content to the end of the
file.
o Binary Handling:
Use 'b' mode to handle binary files and use read() or write() for binary
data.
3. Close the File:
o Use file.close() to close the file and save changes.
o Alternatively, use the with statement to automatically close the file.
4. Handle Exceptions:
o Implement error handling to manage scenarios such as file not found or
permission issues using try and except blocks.
5. File Path Operations:
o Use modules like os and pathlib to manage file paths, check existence, and
delete files.
import os
from pathlib import Path
def create_and_write_file(file_name, content):
"""Create a file and write content to it."""
with open(file_name, 'w') as file:
file.write(content)
print(f"File '{file_name}' created and written to.")
def read_file(file_name):
"""Read content from a file."""
with open(file_name, 'r') as file:
content = file.read()
print(f"Content of '{file_name}':\n{content}")
def append_to_file(file_name, content):
"""Append content to an existing file."""
with open(file_name, 'a') as file:
file.write(content)
print(f"Content appended to '{file_name}'.")
def delete_file(file_name):
"""Delete a file."""
try:
os.remove(file_name)
print(f"File '{file_name}' deleted.")
except FileNotFoundError:
print(f"File '{file_name}' not found.")
def write_binary_file(file_name, binary_data):
"""Write binary data to a file."""
with open(file_name, 'wb') as file:
file.write(binary_data)
print(f"Binary data written to '{file_name}'.")
def read_binary_file(file_name):
"""Read binary data from a file."""
with open(file_name, 'rb') as file:
binary_data = file.read()
print(f"Binary data read from '{file_name}':\n{binary_data}")
def file_operations_demo():
text_file = 'sample.txt'
binary_file = 'sample.bin'
# Creating and writing to a text file
create_and_write_file(text_file, 'Hello, Python file handling!\nThis is a new line.')
# Reading the text file
read_file(text_file)
# Appending to the text file
append_to_file(text_file, '\nAppended line.')
# Reading the text file again to see the appended content
read_file(text_file)
# Creating and writing binary data to a file
binary_data = bytes([120, 3, 255, 0, 100]) # Example binary data
write_binary_file(binary_file, binary_data)
# Reading binary data from the file
read_binary_file(binary_file)
# Deleting the files
delete_file(text_file)
delete_file(binary_file)
if __name__ == "__main__":
file_operations_demo()
ouput:
File 'sample.txt' created and written to.
Content of 'sample.txt':
Hello, Python file handling!
This is a new line.
Content appended to 'sample.txt'.
Content of 'sample.txt':
Hello, Python file handling!
This is a new line.
Appended line.
Binary data written to 'sample.bin'.
Binary data read from 'sample.bin':
b'x\x03\xff\x00d'
File 'sample.txt' deleted.
File 'sample.bin' deleted.
PS C:\Users\sures>
Ex:9 Structured text files
Aim:
The aim of experimenting with parsing different structured text files (CSV, XML, HTML,
and JSON) is to understand the structure and performance implications of each format. This
involves learning how to read, write, and manipulate data in these formats, as well as
comparing their performance in terms of parsing time and memory usage.
Algorithm for Structured Text File Parsing:
1. Parsing CSV Files
1. Create a CSV File:
o Use Python’s csv module to write tabular data to a file.
2. Read and Parse CSV File:
o Open the file using csv.reader to read the content.
o Process each row of the CSV file.
3. Measure Performance:
o Use the time module to measure the time taken to parse large CSV files.
2. Parsing XML Files
1. Create an XML File:
o Use any text editor to create an XML file with nested elements and attributes.
2. Read and Parse XML File:
o Use Python’s xml.etree.ElementTree module to parse the XML file.
o Traverse the XML tree and extract data.
3. Measure Performance:
o Measure the time taken to parse large XML files.
3. Parsing HTML Files
1. Create an HTML File:
o Create an HTML file with various tags and content.
2. Read and Parse HTML File:
o Use Python’s BeautifulSoup library to parse the HTML content.
o Extract data by navigating the HTML tags.
3. Measure Performance:
o Measure the time taken to parse and extract data from large HTML files.
4. Parsing JSON Files
1. Create a JSON File:
o Create a JSON file with nested objects and arrays.
2. Read and Parse JSON File:
o Use Python’s json module to load and parse the JSON data.
o Access the data using Python dictionaries and lists.
3. Measure Performance:
o Measure the time taken to parse large JSON files.
import csv
import timeit
# Sample CSV data
csv_data = """name,age,city
John,23,New York
Jane,29,Los Angeles
Doe,31,Chicago"""
# Write the CSV data to a file
with open("test.csv", "w") as file:
file.write(csv_data)
# Function to parse CSV
def parse_csv():
with open("test.csv", newline='') as csvfile:
reader = csv.DictReader(csvfile)
return [row for row in reader]
# Measure the time to parse CSV
csv_time = timeit.timeit(parse_csv, number=1000)
print(f"CSV Parsing Time: {csv_time:.6f} seconds")
import xml.etree.ElementTree as ET
import timeit
# Sample XML data
xml_data = """<root>
<person>
<name>John</name>
<age>23</age>
<city>New York</city>
</person>
<person>
<name>Jane</name>
<age>29</age>
<city>Los Angeles</city>
</person>
</root>"""
# Write the XML data to a file
with open("test.xml", "w") as file:
file.write(xml_data)
# Function to parse XML
def parse_xml():
tree = ET.parse("test.xml")
root = tree.getroot()
return [{child.tag: child.text for child in person} for person in root]
# Measure the time to parse XML
xml_time = timeit.timeit(parse_xml, number=1000)
print(f"XML Parsing Time: {xml_time:.6f} seconds")
import timeit
from bs4 import BeautifulSoup
# Sample HTML data
html_data = """<html>
<body>
<table>
<tr><td>John</td><td>23</td><td>New York</td></tr>
<tr><td>Jane</td><td>29</td><td>Los Angeles</td></tr>
</table>
</body>
</html>"""
# Write the HTML data to a file
with open("test.html", "w") as file:
file.write(html_data)
# Function to parse HTML
def parse_html():
with open("test.html", "r") as file:
soup = BeautifulSoup(file, 'html.parser')
table = soup.find('table')
return [[cell.text for cell in row.find_all('td')] for row in table.find_all('tr')]
# Measure the time to parse HTML
html_time = timeit.timeit(parse_html, number=1000)
print(f"HTML Parsing Time: {html_time:.6f} seconds")
import json
import timeit
# Sample JSON data
json_data = """
{"name": "John", "age": 23, "city": "New York"},
{"name": "Jane", "age": 29, "city": "Los Angeles"}
"""
# Write the JSON data to a file
with open("test.json", "w") as file:
file.write(json_data)
# Function to parse JSON
def parse_json():
with open("test.json", "r") as file:
return json.load(file)
# Measure the time to parse JSON
json_time = timeit.timeit(parse_json, number=1000)
print(f"JSON Parsing Time: {json_time:.6f} seconds")
EX: 10 a) Simple Web application using Django
Aim:
The aim of this lab is to guide students through the process of setting up a Django
development environment. By the end of this lab, students should be able to:
Steps:
Install Python and verify the installation.
Set up and activate a Python virtual environment.
Install Django within the virtual environment.
Create a new Django project and understand the basic structure.
Run the Django development server and verify that the setup is successful.
Step 1: Set Up Your Django Environment
1. Install Django: Make sure you have Django installed. You can install it using pip if
you haven't already:
bash
Copy code
pip install django
2. Create a Django Project: Create a new Django project by running:
django-admin startproject helloworld_project
Navigate into your project directory:
bash
Copy code
cd helloworld_project
3. Create a Django App: Create a new app within your project:
bash
Copy code
python manage.py startapp helloworld_app
Step 2: Set Up Your Django App
1. Add the App to Your Project: Open helloworld_project/settings.py and add
helloworld_app to the INSTALLED_APPS list:
python
Copy code
INSTALLED_APPS = [
...
'helloworld_app',
2. Create a View: In helloworld_app/views.py, create a simple view that returns a
"Hello, World!" response:
python
Copy code
from django.http import HttpResponse
def hello_world(request):
return HttpResponse("Hello, World!")
3. Set Up URL Routing: Create a URL configuration for your app. In helloworld_app,
create a file named urls.py if it doesn't exist and add the following:
python
Copy code
from django.urls import path
from .views import hello_world
urlpatterns = [
path('', hello_world, name='hello_world'),
Then, include your app's URLs in the project's URL configuration. Open
helloworld_project/urls.py and modify it:
python
Copy code
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('helloworld_app.urls')),
Step 3: Run the Server
1. Apply Migrations: Run the following command to apply any migrations:
bash
Copy code
python manage.py migrate
2. Start the Development Server: Start the server by running:
bash
Copy code
python manage.py runserver
3. View Your Application: Open your web browser and navigate to
http://127.0.0.1:8000/. You should see "Hello, World!" displayed on the page.
That's it! You've created a basic "Hello World" application in Django. If you have any
questions or need further assistance, feel free to ask.
1. Install Django:
o Use pip to install Django.
2. Create a Django Project:
o Use Django’s command-line tools to create a new project.
3. Create a Django App:
o Create an app within the project to handle specific functionality.
2. Developing the Django Web Application
1. Define Models:
o Create models in myapp/models.py to represent the data structure.
2. Create and Apply Migrations:
o Create database tables based on models.
3. Define Views:
o Create views in myapp/views.py to handle HTTP requests.
4. Create Templates:
o Create HTML templates in myapp/templates/myapp/ for rendering data.
5. Define URLs:
o Map URLs to views in myapp/urls.py and myproject/urls.py.
6. Run the Development Server:
o Start Django’s development server to test the application.
Ex:10b simple web application using the Django web framework
Aim:
The aim of developing a simple web application using the Django web framework is to
understand how Django facilitates web development and to evaluate the application's
performance under various loads and scenarios. This involves learning the basics of Django,
implementing a simple web application, and assessing its performance to ensure it meets the
required standards.
Algorithm for Developing and Evaluating a Django Web Application:
Getting Started with Django
1. Installation:
bash
Copy code
pip install django
2. Creating a Django Project:
bash
Copy code
django-admin startproject myproject
cd myproject
3. Running the Development Server:
bash
Copy code
python manage.py runserver
This command starts a development server on http://127.0.0.1:8000/.
4. Creating a Django App:
bash
Copy code
python manage.py startapp myapp
An app is a web application that does something, e.g., a blog or a forum.
5. Defining Models: In myapp/models.py, define your data models using Django's
ORM:
python
Copy code
from django.db import models
class MyModel(models.Model):
name = models.CharField(max_length=100)
description = models.TextField()
6. Making Migrations:
bash
Copy code
python manage.py makemigrations
python manage.py migrate
7. Creating an Admin User:
bash
Copy code
python manage.py createsuperuser
Follow the prompts to create an admin user.
8. Registering Models with Admin: In myapp/admin.py:
python
Copy code
from django.contrib import admin
from .models import MyModel
admin.site.register(MyModel)
9. URL Configuration: In myproject/urls.py:
python
Copy code
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('myapp/', include('myapp.urls')),
10. Creating Views: In myapp/views.py:
python
Copy code
from django.shortcuts import render
from .models import MyModel
def my_view(request):
items = MyModel.objects.all()
return render(request, 'myapp/template.html', {'items': items})
11. Templates: Create an HTML template in myapp/templates/myapp/template.html:
html
Copy code
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
</head>
<body>
<h1>Items</h1>
<ul>
{% for item in items %}
<li>{{ item.name }}: {{ item.description }}</li>
{% endfor %}
</ul>
</body>
</html>
12. Running the Server:
bash
Copy code
python manage.py runserver
Visit http://127.0.0.1:8000/myapp/ to see your app in action.
3. Evaluating Performance
1. Load Testing:
o Use tools like Apache JMeter or Locust to simulate traffic and measure how
the application handles load.
o Create test scripts to simulate user interactions and assess performance under
different loads.
2. Profiling and Monitoring:
o Use Django’s built-in profiling tools or third-party tools like Django Debug
Toolbar to analyze performance.
o Monitor application performance and resource usage using tools like New
Relic or Datadog.
3. Database Performance:
o Optimize database queries and use indexing to improve performance.
o Use Django’s query optimization techniques to reduce database load.
4. Stress Testing:
o Identify and test the limits of the application to see how it performs under
extreme conditions.
o Use stress testing tools to simulate high traffic and observe how the
application responds.
5. Scalability Testing:
o Test how the application scales by increasing the number of users or requests.
o Evaluate performance with load balancing and multiple server instances.
Ex.11 Programs on Parallel Computing
Aim:
The aim is to measure and compare the performance of parallel computing techniques (CPU
cores, threads, and multiprocessing) against sequential execution for a specific computational
task. This helps in understanding the benefits and trade-offs of parallel computing in terms of
execution time and resource utilization.
Algorithm:
1. Define the Task
Choose a computationally intensive task suitable for parallelization. Examples include:
Matrix multiplication
Numerical integration
Sorting large datasets
2. Implement Sequential Execution
Create a basic implementation of the chosen task using a sequential approach.
3. Implement Parallel Computing Techniques
Implement the same task using different parallel computing techniques:
CPU Cores: Use parallelism provided by multi-core CPUs.
Threads: Use multithreading to parallelize the task within a single process.
Multiprocessing: Use multiple processes to parallelize the task, potentially across
multiple cores.
4. Measure Performance
Evaluate and compare the performance of each implementation by measuring execution time
and other relevant metrics.
5. Analyze Results
Compare the performance of parallel implementations with the sequential implementation to
understand the benefits of each parallel computing technique.
Detailed Implementation:
1. Define the Task: Matrix Multiplication
Matrix multiplication is a computationally intensive task that benefits from parallel
processing.
2. Sequential Implementation
python
Copy code
import numpy as np
import time
def matrix_multiply_sequential(A, B):
return np.dot(A, B)
# Create random matrices
size = 1000
A = np.random.rand(size, size)
B = np.random.rand(size, size)
# Measure execution time
start_time = time.time()
C = matrix_multiply_sequential(A, B)
end_time = time.time()
print(f"Sequential execution time: {end_time - start_time} seconds")
3. Parallel Implementation Using Threads
python
Copy code
import numpy as np
import time
from threading import Thread
def matrix_multiply_worker(A, B, C, row_start, row_end):
for i in range(row_start, row_end):
C[i, :] = np.dot(A[i, :], B)
def matrix_multiply_threads(A, B, num_threads):
size = A.shape[0]
C = np.zeros((size, size))
threads = []
rows_per_thread = size // num_threads
for i in range(num_threads):
row_start = i * rows_per_thread
row_end = (i + 1) * rows_per_thread if i != num_threads - 1 else size
thread = Thread(target=matrix_multiply_worker, args=(A, B, C, row_start, row_end))
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
return C
# Measure execution time
num_threads = 4
start_time = time.time()
C = matrix_multiply_threads(A, B, num_threads)
end_time = time.time()
print(f"Threads execution time: {end_time - start_time} seconds")
4. Parallel Implementation Using Multiprocessing
python
Copy code
import numpy as np
import time
from multiprocessing import Pool, cpu_count
def matrix_multiply_worker(A_row, B):
return np.dot(A_row, B)
def matrix_multiply_multiprocessing(A, B, num_processes):
size = A.shape[0]
C = np.zeros((size, size))
with Pool(processes=num_processes) as pool:
rows = [A[i, :] for i in range(size)]
results = pool.starmap(matrix_multiply_worker, [(row, B) for row in rows])
C = np.array(results)
return C
# Measure execution time
num_processes = cpu_count()
start_time = time.time()
C = matrix_multiply_multiprocessing(A, B, num_processes)
end_time = time.time()
print(f"Multiprocessing execution time: {end_time - start_time} seconds")