Sunday, 24 December 2023

Python File Handling

File Handling

File handling is an important part of any web application. 
Python provides inbuilt functions for creating, writing, and reading files.
There are two types of files that can be handled in python,normal text
files and binary files.

By using the below modes we can read or write into the files 

There are four different methods (modes) for opening a file: 
"r" - Read - Default value. Opens a file for reading, error if the file does
not exist 
"a" - Append - Opens a file for appending, creates the file if it does not
exist 
"w" - Write - Opens a file for writing, creates the file if it does not exist
"x" - Create - Creates the specified file, returns an error if the file exists 
"t" - Text - Default value. Text mode 
"b" - Binary - Binary mode (e.g. images) 

We can perform read and write simultaniously by using the below modes

Read and Write (‘r+’): Open the file for reading and writing. The
handle is positioned at the beginning of the file. Raises I/O error if the
file does not exist. 
Write and Read (‘w+’) : Open the file for reading and writing. For an
existing file, data is truncated and over-written. The handle is
positioned at the beginning of the file. 
Append and Read (‘a+’) : Open the file for reading and writing. The file
is created if it does not exist. The handle is positioned at the end of the
file. The  data being written will be inserted at the end, after the existing
data. 

xb -- create binary
wb -- write binary 
ab -- append binary 
rb -- read binary


file built in functions -- open()
file built in methods -- read()--reads entire file ,readline() -- here we need to give number to read those many charecters,readlines() -- it prints all lines in the form of list. -- all these are for to read
write() -- to write
close() -- to close
seek() -- To change file position 
tell() -- Returns the currentfile position

--Create file example
f = open("C:/Desktop/file.txt", "x")
f.close()  

--To open a file and write
--Write method will delete the old data and writes new data.
f = open("file.txt", "w") 
f.write("hellow")
f.close()
-- Append method
f.append("hellow")
f.close()

By looping through the lines of the file, you can read the whole file, line by line: 
f = open("C:/Desktop/file.txt", "r")
for x in f: 
    print (x)
f.close()


Saturday, 23 December 2023

SQLite3 Database

import sqlite3
# For connecting to the database. If the database is not in the system, it will create and connect to the database
con = sqlite3.connect("mydatabase1.db")
# If you want to create a table or insert data into the table, declare a cursor
cur = con.cursor()
# By using execute, we can create a table and execute the table
cur.execute('''
    CREATE TABLE IF NOT EXISTS students (
        name VARCHAR(50),
        rollno VARCHAR(50),
        section VARCHAR(50)
    )
''')
con.commit()
cur.execute('INSERT INTO students VALUES ("sai", "511A", "sectionA")')
cur.execute('INSERT INTO students VALUES ("ramesh", "512A", "sectionB")')
cur.execute('INSERT INTO students VALUES ("raju", "513A", "sectionC")')
con.commit()
con.close() 

Output can be seen from below Query 

import sqlite3
con=sqlite3.connect("mydatabase.db")
cur=con.cursor()
b=cur.execute('select * from students')
print(b.fetchall())
con.close()

Thursday, 21 December 2023

tkinter

 Please find the Basic Code to write tkinter Programme 

'''By using lable method we can create text , by using entry method we can create box
pack(),grid() and place() are geometry managers'''
# Importing the tkinter
from tkinter import *
import sqlite3
import tkinter as tk

# Initializing the screen
win = tk.Tk()

win.geometry("400x400+10+20")

#Creating the lable
l=Label(win, text='Hellow Nagendra')
# Adding lable to the window
l.pack()
#Creating the entry
e=Entry(win)
e.pack()
#creating the button
b=Button(win, text='Button1')
# Adding Button to the window
b.pack()
# Creating the Text Widget
t=Text(win,width=30,height=10)
# Adding text to the window
t.pack()
# Creating Check Box
c = Checkbutton(win,text='Yes')
# Adding Checkbox to the window
c.pack()
# Creating Radio button
r = Radiobutton(win,text='Yes')
# Adding radio button to the window
r.pack()

# Adding the Option Menu
v=StringVar()
o=OptionMenu(win,v,'Python',*('RAM','kan','Jyo','Tul'))
o.pack()
# Adding the Scale
s=Scale(win,from_=0,to=100)
s.pack()


###you can add widgets here. This is used to start the application
win.mainloop()

Interview Prepatarion -

 

Please follow below sites to learn and Crack Pytohn Interview's

leetcode.com 
hackerrank.com 
kaggle.com 
exercism.io
projecteuler.net
DevProjects
codewars.com
hackerearth.com
codechef.com 
geeksforgeeks.org 
coderbyte.com
w3schools.com 
codeforces.com
replit.com
###################################################################################
GIT Architecture

Git architecture and workflow

Multiple contributors can work on the same project at once thanks to the distributed version control system known as Git. Each developer in Git has a local repository that contains an exact replica of the project’s history. Local commits are followed by pushes to a central repository, which is typically housed on a platform such as GitHub or GitLab. As merging and conflict resolution are fundamental components of the Git workflow, this enables collaboration without causing constant overwriting of one another’s work.

Let’s examine a few of the fundamental Git commands you’ll frequently use:

  • Clone: You can copy an existing repository to your local machine using the [Repository_url] git clone command.
  • Commit: When you commit, your changes are saved to the local repository. Git add [file_names] is used to stage changes prior to committing, and git commit -m Commit message is used to commit the staged changes.
  • Push: This sends your committed changes to your remote repository. GitHub push origin [branch_name].
  • Pull: This updates your local repository by downloading updates from a remote repository to your computer. [Branch_name] git pull origin.

After laying a solid foundation in the fundamentals of Git, let’s move on to the next subject: exploring branches, merges, and best practices for efficiently managing challenging data engineering projects.

Let’s look at an instance where you’re tasked with adding a new data validation feature to an already existing ETL pipeline as a data engineer. If your team uses the Git workflow, you will branch off the develop branch and work on your changes in a new branch called feature. When your feature branch is finished, you will start a pull request to merge it back into the develop branch. Eventually, this will be merged into the main branch as part of a planned release.

Consider a different scenario in which you and another engineer are tasked with improving various components of an algorithm for processing data. You both make adjustments to different branches. Git flags a conflict when merging these branches because both of you changed the same method. To fix this, you would manually select which changes to keep in the conflicting file, possibly integrating both sets of optimizations, before successfully completing the merge.

Git collaboration involves more than just pushing your changes; it also involves staying in sync with other people. You can keep your local repository updated with the most recent changes from your team by using the git pull and git fetch commands. git fetch gives you an additional level of control by allowing you to review the changes before merging, in contrast to git pull, which will fetch the changes and immediately merge them into your current branch.

Imagine you are a member of a distributed team in charge of a sizable data pipeline. A global teammate of yours has made some improvements and pushed them to the remote repository. Before merging these changes into your local branch for additional testing, you can use git fetch to verify them.

###################################################################################

Tuesday, 19 December 2023

Regular expressions in Python

#Regular expressions - 

Checking the documentation of re 

import re
help(re)
dir(re)

The re.compile() function returns a regular expression object. This object represents the compiled version of the regular expression pattern.
import re
pattern = re.compile(r'\d+')  # This pattern matches one or more digits.

So, in the regular expression pattern \d{4}, \d is used to match exactly one digit, and {4} specifies that this digit should occur exactly four times in sequence. Therefore, \d{4} is a pattern that matches sequences of four consecutive digits.

string = "The Euro STOXX 600 index, which tracks all stock markets across Europe including the 
FTSE, fell by 11.48% – the worst day since it launched in 1998. The panic selling prompted by 
the coronavirus has wiped £2.7tn off the value of 
STOXX 600 shares since its all-time peak on 19 
February."

import re

# Define a raw string with a regular expression pattern
s = r"\d{4}"

# Compile the regular expression pattern
t = re.compile(s)

# Use the compiled pattern to find all occurrences in the string
result = re.findall(t, string)

# Print the result
print(result)

###################################################################################

>>> import re
>>> result = re.search(r"\d{3}", string)
>>> result
<re.Match object; span=(15, 18), match='600'>

So, in the regular expression pattern \d{4}, \d is used to match exactly one digit, and {4} specifies that this digit should occur exactly four times in sequence. Therefore, \d{4} is a pattern that matches sequences of four consecutive digits.

###################################################################################

Here's a brief breakdown of how the pattern works:

\w: Match a single word character (alphanumeric character or underscore).
{3}: Match exactly three occurrences of the preceding word character

>>> result = re.match(r"\w{3}", string)
>>> result
<re.Match object; span=(0, 3), match='The'>

###################################################################################

>>> result = re.findall(r"\d{3}", string)
>>> result
['600', '199', '600']
###################################################################################

>>> result = re.split(r"\s", string)
>>> result
['The', 'Euro', 'STOXX', '600', 'index,', 'which', 'tracks', 'all', 'stock', 'markets', 'across', 'Europe', 'including', 'the', '', 'FTSE,', 'fell', 'by', '11.48%', '–', 'the', 'worst', 'day', 'since', 'it', 'launched', 'in', '1998.', 'The', 'panic', 'selling', 'prompted', 'by', 'the', 'coronavirus', 'has', 'wiped', '£2.7tn', 'off', 'the', 'value', 'of', 'STOXX', '600', 'shares', 'since', 'its', 'all-time', 'peak', 'on', '19', 'February.']

###################################################################################

>>> result = re.sub(r"[A-Z]{2,}", "INDEX",string)
>>> result
'The Euro INDEX 600 index, which tracks all stock markets across Europe including the  INDEX, fell by 11.48% – the worst day since it launched in 1998. The panic selling prompted by the coronavirus has wiped £2.7tn off the value of INDEX 600 shares since its all-time peak on 19 February.'

In simpler terms, the re.sub() function is replacing any sequence of two or more consecutive uppercase letters in the original string with the word "INDEX".

###################################################################################

>>> result = re.findall(r"the", string)
>>> result
['the', 'the', 'the', 'the']

###################################################################################
'''Prints three charecters of decimals'''
string = "The Euro STOXX 600 index, which tracks all stock markets across Europe including the FTSE, fell by 11.48% – the worst day since it launched in 1998. The panic selling prompted by the coronavirus has wiped £2.7tn off the value of STOXX 600 shares since its all-time peak on 19 February."
import re
result = re.findall(r"\d{3}", string)
print(result)
###################################################################################
'''Spilts all words into List of charecters '''
string = "The Euro STOXX 600 index, which tracks all stock markets across Europe including the FTSE, fell by 11.48% – the worst day since it launched in 1998. The panic selling prompted by the coronavirus has wiped £2.7tn off the value of STOXX 600 shares since its all-time peak on 19 February."
import re
result = re.split(r"\s", string)
print(result)
###################################################################################
'''It will remove the Index charecter'''
import re
pattern = r'\d+'  # This is a regular expression pattern to match one or more digits
replacement = 'X'
text = 'There are 123 apples and 456 oranges.'
result = re.sub(pattern, replacement, text)
print(result)
'''Output -- There are X apples and X oranges.'''
###################################################################################

Friday, 15 December 2023

Handling Strings

 /* Attributes starting with underscores are often considered private in Python for Dir() method, and this condition is used to filter out private attributes which starts with __(underscore).

text = Python

 >>> print(dir(text))

Use the Dir() function to list all the methods and attributes of the python Object.

print(help(text.startswith))    -- It will tell how to use the String method.

text = Python

>>> for method in dir(text):
...     if method.startswith("_")  :
...         continue
...     print(method)
capitalize
casefold
center
count

Thursday, 14 December 2023

Python Fundamentals



For Python Tutorials Follow this link

https://docs.python.org/3/faq/index.html

Learn Python in 10 min
>>> help(5)
Help on int object:
(etc etc)

>>> dir(5)
['__abs__', '__add__', ...]

>>> abs.__doc__
'abs(number) -> number
# Creating Virtaul Environment 

For creating Virtual environment Use the Below command

python -m venv env -- For creating new virtual environement

For Activating the Virtaul Environment 
.\env\Scripts\activate -- For activating virtual environment.

or
.\activate

For installing the Modules 

Then install using PIP

For Deactivating the Virtual Environment 

deactivate -- For deactiving virtual environment.

##########################################################################################

#The Usage of *args and **kwargs
*args --- It accepts any no of positional arguments like list,String,integers and Varchar
**kwargs --- It accepts only Dictionary Arguments .
Let's see some basic examples on this 

>>> def example_function(*args):
...     for arg in args:
...         print(arg)
...
>>> example_function(1, 2, "hello", [3, 4])
1
2
hello
[3, 4]

and

>>> def example_function(**kwargs):
...     for key, value in kwargs.items():
...         print(key, ":", value)
...
>>> example_function(name="Alice", age=25, city="Wonderland")
name : Alice
age : 25
city : Wonderland
##########################################################################################

# Python Code formatter 
Install the Below IDE to write the Python code which will correct the errors in VSCode 
  • Pylint
PIP install Pylint
and then write the code in VsCode
##########################################################################################

# Using Python connecting to the sqlite database.
import sqlite3
try:
   
    # Connect to DB and create a cursor
    sqliteConnection = sqlite3.connect('sql.db')
    cursor = sqliteConnection.cursor()
    print('DB Init')
 
    # Write a query and execute it with cursor
    query = 'select sqlite_version();'
    cursor.execute(query)
 
    # Fetch and output result
    result = cursor.fetchall()
    print('SQLite Version is {}'.format(result))
 
    # Close the cursor
    cursor.close()
 
# Handle errors
except sqlite3.Error as error:
    print('Error occurred - ', error)
 
# Close DB Connection irrespective of success
# or failure
finally:
   
    if sqliteConnection:
        sqliteConnection.close()
        print('SQLite Connection closed')
                               
##########################################################################################

# Python enumerate Function 

The enumerate function is used to iterate over a sequence (such as a list, tuple, or string) while keeping track of the index (position) of the current item. It returns pairs of the form (index, element). This can be particularly useful in loops where you need both the index and the corresponding value.

example-

seasons = ['Spring', 'Summer', 'Fall', 'Winter']
list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]


The enumerate() function takes a collection (e.g. a tuple) and returns it as an key, value pair

##########################################################################################

# Using format Option in Print statement

>>> name = "Jyothi Nagendra"
>>> age = 34
>>> city = "Bhimavaram"
>>>
>>> # Using format option in print statement
>>> print("Name: {}, Age: {}, City: {}".format(name, age, city))
Name: Jyothi Nagendra, Age: 34, City: Bhimavaram

In this example, the curly braces {} act as replacers, and the format method is used to replace them with the values of the variables name, age, and city.

##########################################################################################
#Using f-strings

you can also use f-strings (formatted string literals) in the print statement

>>> name = "John"
>>> age = 25
>>> city = "New York"
>>>
>>> # Using f-string in print statement
>>> print(f"Name: {name}, Age: {age}, City: {city}")
Name: John, Age: 25, City: New York

here directly we can replace the flower braces with the values without format option by using f strings

##########################################################################################

# Using  floating-point number

# Example floating-point number
>>> pi = 3.141592653589793
>>>
>>> # Using f-formatting to print with 2 decimal places
>>> print(f"Value of pi: {pi:.2f}")
Value of pi: 3.14

In this example, :.2f inside the curly braces indicates that the floating-point number pi should be formatted with two decimal places. 

##########################################################################################

# Dunder Methods --

In Python, "dunder" is short for "double underscore," and "dunder methods" refer to special methods with names that start and end with double underscores.
They are used to define behavior for built-in operations in Python classes. For example, the __init__ method is a dunder method that is automatically called when an object is created.
By Default these dunder methods will be there if we create any class. These methods by default it will be there in object class since this object class acts as a parent for every class .

# Example to show dunder methods in a Class
Class A:
      pass

print(dir(A))
print(dir(obj))

Class A:
      pass

obj=A()
str(obj) 

When srring,arthemetic operation etc if we use by default it will look for the dunder method (__str__) in Class A if it is  not there it will check for parent object class and fetch it.
When we call object from methods like str,arthemetic operators ,class,len,in,abs,+,and,ceil,complex,contains,del,==,float,floor(math module),>=, then dunder methods (__) will be called  parent class of class is object class . 

Reference check this link from youtube.
https://www.youtube.com/watch?v=Dmp80lD_28U&list=PLwJGL4B6ur8zED5BCn8ms2GJrIPz8QEj9&index=122&pp=iAQB

##########################################################################################

# Python Generator Function 

In Python, a generator function is a special type of function that allows you to iterate over a potentially large sequence of data without creating the entire sequence in memory at once. It produces values one at a time using the yield keyword. When a generator function is called, it returns a generator object, which can be iterated over to retrieve the values produced by the yield statements.

>>> def myGenerator():
...     print('First Item')
...     yield 10
...     print('Second Item')
...     yield 20
...     print('Third Item')
...     yield 30
...
>>> gen = myGenerator()
>>>
>>> # Call next to advance the generator to the next yield statement
>>> next(gen)
First Item
10
>>>
>>> next(gen)
Second Item
20
>>> next(gen)
Third Item
30
##########################################################################################

Python Nested Loops Syntax:
-------------------------------------
Outer_loop Expression:
    Inner_loop Expression:
            Statement inside inner_loop
    Statement inside Outer_loop
##################################################################################
What is a List comprehension ?
List comprehension is a syntax construction to ease the creation of a list based on the existing iterable.

What is / and // in python 
// represents the floor division where as / represents precise division 
5//2 - 2
5/2- 2.5
###################################################################################
Instance Method Vs Class Method Vs Static Method 

Instance methods are used for operations that involve the instance of the class. Operate on instance data.Call On object instance

Class methods are used for operations that involve the class as a whole. Operate on class data or modify class behavior. Call on On class itself.

Static methods are used when a method doesn't need access to the instance or the class and can be thought of as standalone functions within the class. Function-like actions associated with a class but don't need access to class or instance data. Call On class or instance (no special first argument)

When I say "operate on instance data," I mean that instance methods can directly access and modify the data that's unique to each object (instance) of a class.

Here's a more detailed explanation:

  • Instance Data: Each object created from a class has its own set of attributes, called instance attributes. These attributes store the object's specific data, making each object unique.
  • Instance Methods: These methods are designed to work with this instance-specific data. They have access to the object's attributes through the self argument, allowing them to read, modify, and use those attributes.
class Person:
    def __init__(self, name, age):
        self.name = name  # Instance attribute
        self.age = age    # Instance attribute

    def greet(self):  # Instance method
        print("Hello, my name is", self.name)  # Accessing instance attribute

    def celebrate_birthday(self):  # Instance method
        self.age += 1  # Modifying instance attribute

person1 = Person("Alice", 30)
person1.greet()  # Output: Hello, my name is Alice (accessing instance data)
person1.celebrate_birthday()  # Modifying instance data
print(person1.age)  # Output: 31 (reflecting the change)

Key points:

  • Instance methods are called on individual objects, not the class itself.
  • They receive the object instance as self in their first argument.
  • They can access and modify any instance attributes of that object.
  • Each object's instance attributes are independent of other objects' attributes.

---------------------------------------------------------------------------------------------------------------------------
Class Methods-
-------------
When I say "class data," I'm referring to data that's shared by all instances of a class, rather than being specific to individual objects.

Here's a more detailed explanation:
Class Attributes: These attributes are defined directly within the class body, outside of any methods. They are shared by all instances of the class, meaning they have the same value for every object created from that class.
Accessing Class Data: Class methods and static methods can directly access and modify class attributes using the cls argument (for class methods) or by directly referencing the class name.

class Person:
    species = "Homo sapiens"  # Class attribute
    total_count = 0  # Class attribute (used for counting instances)

    def __init__(self, name, age):
        self.name = name  # Instance attribute
        self.age = age    # Instance attribute
        Person.total_count += 1  # Modifying class attribute

    @classmethod  # Class method
    def get_species(cls):
        return cls.species  # Accessing class attribute

    @classmethod  # Class method
    def get_total_count(cls):
        return cls.total_count  # Accessing and modifying class attribute

person1 = Person("Alice", 30)
person2 = Person("Bob", 25)

print(Person.get_species())  # Output: Homo sapiens (accessing class data)
print(Person.get_total_count())  # Output: 2 (reflecting the count of instances)

----------------------------------------------------------------------------------------------------------------------------
Static Method Example 

class Person:
    @staticmethod
    def is_adult(age):
        return age >= 18

Person.is_adult(25)  # Output: True

###################################################################################

can we modify class data by using getter setter methods in python ?

Yes, you can modify class data using setter methods in Python, but not directly with getter methods. Here's how they work:

class Person: @property def name(self): return self._name @name.setter def name(self, new_name): self._name = new_name

Modifying data using a setter methods outside the class: person = Person() person.name = "Alice" # This calls the setter method to set the name

Getter methods: Primarily provide a way to retrieve the value of an attribute Defined using the @property decorator.GETTER methods are (READ ONLY PROPERTY) while the SETTER methods are READ WRITE property.
While they cannot directly modify data, they can indirectly trigger changes through other methods or logic within their code.

Key points: Setter methods are essential for controlled modification of class data, ensuring data integrity and consistency. Getter methods, while not directly modifying data, play a crucial role in encapsulation and controlled access to class attributes. Together, getters and setters promote a well-structured and maintainable object-oriented design.

##########################################################################
Escape Characters

>>> print('Hi this is Nagendra\'s blog') Hi this is Nagendra's blog

Here to escape ' in Nagendra's I am using \ as a character .
\n -- New Line Charecter
\b -- BackSpace
\t -- Tab
\ -- Escape Symbol
##########################################################################
Constructer in Python
When ever if you declare Object , through that object we will call class methods ,but when we declare constructer inside a class example __init__ by default these will be invoked with out calling those by using Objects. These are called constructers in Python .
##########################################################################
# What does the Join Method do

Join method joins the elements in the List by using the separator which is used Infront of the Join. Please find the output below for reference .

# If `line` was initially a list like this: line = ["apple", "banana", "cherry"] # After `line = "-".join(line)`, it becomes: line = "apple-banana-cherry"
##########################################################################
# What is a Numpy Array

The NumPy (Numeric Python) package helps us manipulate large arrays and matrices of numeric data. To use the NumPy module, we need to import it using: import numpy Arrays A NumPy array is a grid of values. They are similar to lists, except that every element of an array must be the same type. import numpy a = numpy.array([1,2,3,4,5]) print a[1] #2 b = numpy.array([1,2,3,4,5],float) print b[1] #2.0 In the above example, numpy.array() is used to convert a list into a NumPy array. The second argument (float) can be used to set the type of array elements.
##########################################################################

What is 1D,2D and 3D array

1D represents single list of elements.
import numpy as np

# Create a 1D array
numbers = np.array([1, 2, 3, 4, 5])
print(numbers)  # Output: [1 2 3 4 5]

2D represents a data in a matrix like structure 
# Create a 2D array
matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(matrix)  # Output:
# [[1 2 3]
#  [4 5 6]
#  [7 8 9]]

3D Represent data in a cube-like structure, with multiple 2D arrays stacked together.
# Create a 3D array
cube = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
print(cube)  # Output:
# [[[ 1  2  3]
#   [ 4  5  6]]

#  [[ 7  8  9]
#   [10 11 12]]]

You can access elements using indexing:
numbers[0] : Accesses the first element of the 1D array.
matrix[1, 2] : Accesses the element at row 1, column 2 of the 2D array.
cube[0, 1, 0] : Accesses the element at the first 2D array, second row, first column of the 3D array.

################################################################################
Merging the dictionaries

Using | operator

name1 = {"kelly": 23, "Derick": 14, "John": 7} name2 = {"Ravi": 45, "Mpho": 67} names = name1 | name2 print(names)

Using the merge ( ** ) operator

name1 = {"kelly": 23, "Derick": 14, "John": 7} name2 = {"Ravi": 45, "Mpho": 67} names = {**name1, **name2} print(names)
################################################################################
Counting the Item Occurrences , Writing by using the loops

list1 = ['John','Kelly', 'Peter', 'Moses', 'Peter']
# Create a count variable 
count = 0
for name in list1:
    if name == 'Peter':
       count +=1
print(f'The name Peter appears in the list' f' {count} times.')

################################################################################
Understanding the GLOBAL variables inside the function

numbers = [1, 2, 3] # Global list def modify_list(): numbers.append(4) # Appends to the global list (works without global keyword) def modify_scalar(): global x # Declare x as global x = 10 # Modifies the global x x = 5 # Global scalar variable modify_list() print(numbers) # Output: [1, 2, 3, 4] modify_scalar() print(x) # Output: 10
################################################################################
sys.argv -- How to use this as command line arguments

save the below code into test.py and run the code in python terminal by passing the arguments .

import sys print ("Number of arguments:", len(sys.argv), "arguments") print ("Argument List:", str(sys.argv)) $ python test.py arg1 arg2 arg3 Number of arguments: 4 arguments. Argument List: ['test.py', 'arg1', 'arg2', 'arg3']
################################################################################
Writing output to the JSON file

import json

data = {
    "name": "Bard",
    "skills": ["coding", "writing", "humor"],
    "interests": {"music": "classical", "movies": "sci-fi"}
}

with open("output.json", "w") as f:
    json.dump(data, f, indent=4)

print("Data written to output.json")
#################################################################################
Reading JSON data from the String

json_string = '[{"name": "Jane", "age": 25, "interests": ["music", "books"]}, {"name": "Tom", "age": 40, "job": "doctor"}]'

import json

# Load the JSON string
data = json.loads(json_string)

# Loop through each object
for person in data:
    print(f"Name: {person['name']}")
    print(f"Age: {person['age']}")
    
    # Access and print a specific value based on a key
    if "interests" in person:
        print(f"Interests: {person['interests']}")
    elif "job" in person:
        print(f"Job: {person['job']}")

print("----------")
###################################################################################

Q: Is there an easy way to tell if a variable is immutable or mutable? A: Well…there’s the rule: numbers, strings, booleans, and tuples are immutable, whereas most everything else is mutable (such as lists, sets, and dictionaries). Things can get a little more complicated if you try to determine this at runtime. One possible technique is to pass your variable to the hash built-in. If the passed-in variable is immutable, hash returns a number. If the passed-in variable is mutable, hash fails with a TypeError, which you’d have to code for with some sort of exception-handling code. But, we might be getting ahead of ourselves here.

x = "hello" hash(x) # Returns a hash value (strings are immutable) y = [1, 2, 3] hash(y) # TypeError: unhashable type: 'list' (lists are mutable)

###################################################################################
Python Exception Handling


try: # Code that might raise an exception except ExceptionType1: # Code to handle ExceptionType1 except ExceptionType2: # Code to handle ExceptionType2 ... else: # Code to execute if no exception occurs finally: # Code to execute always, regardless of whether an exception occurs or not

Explanation: try block: Encloses the code that might raise an exception. If no exceptions occur, execution continues normally. except blocks: Handle specific types of exceptions that might be raised in the try block. You can have multiple except blocks to handle different exception types. If an exception occurs, the corresponding except block is executed, and the rest of the try block is skipped. else block (optional): Executes only if no exceptions occur in the try block. Useful for code that should run only when there are no errors. finally block (optional): Always executes, regardless of whether an exception occurs or not. Often used for cleanup tasks, such as closing files or releasing resources.

Example Program
try: num = int(input("Enter a number: ")) result = 10 / num except ValueError: print("Invalid input. Please enter a number.") except ZeroDivisionError: print("Cannot divide by zero.") else: print("The result is:", result) finally: print("This code always executes.")

Use specific exception types in except blocks for better handling. The else block is optional and often used for code that should run only when there are no errors. The finally block is also optional but often used for cleanup tasks, ensuring they're always executed. This structure promotes cleaner and more error-resilient code.
###################################################################################

What is sys.exc_info() in except block of python :

  • This function returns a tuple with three items:   (type, value, traceback).
##########################################################################
try:
 print(100/0) 
 
except:
 print(sys.exc_info()[1] , 'Exception occured') 
 
else:
 print('No exception occurred') 
finally:
 print('Run this block of code always')  


In Python, sys.exc_info()[1] accesses the second item of the tuple returned by the sys.exc_info() function, which represents the current exception being handled.
It's typically an instance of an exception class, such as ValueError, TypeError, ZeroDivisionError, etc.
It holds details about the error, including its message and any relevant data.
If no exception is being handled, sys.exc_info() returns a tuple of three None values.
It's generally preferred to use more specific exception handling techniques with try...except blocks, but sys.exc_info() can be useful in certain debugging or error-handling scenarios.
###################################################################################
How to handle Specific exceptions in Except block 

try:
    num = int(input("Enter a number: "))
    result = 10 / num
except ValueError:
    print("Invalid input. Please enter a number.")
except ZeroDivisionError:
    print("Cannot divide by zero.")
except Exception as e:  # Catch-all for any other unexpected errors
    print("An unexpected error occurred:", e)
else:
    print("The result is:", result)
finally:
    print("This code always executes.")

###################################################################################

Python Decorators 

# Apply multiple decorator on a single function
def InstallDecorator1(func):
 def wrapper():
 print('Please accept terms & conditions...\n')
 func()
 return wrapper
def InstallDecorator2(func):
 def wrapper():
 print('Please enter correct license key...\n')
 return func()
 return wrapper
def InstallDecorator3(func):
 def wrapper():
 print('Please enter partitioning choice...\n')
 return func()
 return wrapper
@InstallDecorator1
@InstallDecorator2
@InstallDecorator3
def InstallLinux():
 print('Linux installation has started \n')
InstallLinux()

@ symbol: The @ symbol is used to apply decorators to the InstallLinux function.
Order of decorators: The order in which decorators are applied is crucial, as they are executed in reverse order. In this case, the order is:
@InstallDecorator3
@InstallDecorator2
@InstallDecorator1

Function Execution:

Calling InstallLinux(): When you call InstallLinux(), the following sequence occurs:
InstallDecorator3: Its wrapper function prints "Please enter partitioning choice..."
InstallDecorator2: Its wrapper function prints "Please enter correct license key..."
InstallDecorator1: Its wrapper function prints "Please accept terms & conditions..."
InstallLinux(): Finally, the original InstallLinux function executes, printing "Linux installation has started".

Output:

Please enter partitioning choice...
Please enter correct license key...
Please accept terms & conditions...
Linux installation has started

###################################################################################

SQL -

 Window Functions -  Window function: pySpark window functions are useful when you want to examine relationships within group of data rather...