Python Notes 2020
Python Notes 2020
Section Heading
1 Core Python Concepts
2 Automating (Daily Business) task using Python
3 Advanced Python Concepts
For Windows
Step 1: Download the Python 3 Installer
Open a browser window and navigate to the Download page for Windows at python.org.
Underneath the heading at the top that says Python Releases for Windows, click on the link
for the Latest Python 3 Release - Python 3.x.x. (Prefer Python 3.6)
Scroll to the bottom and select either Windows x86-64 executable installer for 64-bit
or Windows x86 executable installer for 32-bit.
Then just click Install Now. That should be all there is to it. A few minutes later you should have
a working Python 3 installation on your system.
Installation steps
For any version https://realpython.com/installing-python/
of Linux or Mac
Python Programming(Core+ Advanced) By Rocky Sir 7
Check Python working or not ?
1> After Python installation on Windows, check for path either :
C:\Python36
or
C:\Users\(Your logged in User)\AppData\Local\Programs\Python\Python36
In the 2nd case, Cut the Python36 folder and place it in directly under Program files
C:\Program Files\Python36
2> Go to cmd prompt, change path to C:\Program Files\Python36 & type
> python
// this would open python in interactive mode
>>>
Type Some code, like : Interactive Mode Programming
>>> print("hi all")
// see the o/p. This confirms the python interpreter is correctly installed.
Now to come out of this interactive shell, type
>>> quit()
3> Now, create folder say "suven" where we would dump all our .py code files.
Python Programming(Core+ Advanced) By Rocky Sir 8
4> Now open your text editor say "Notepadd++". [We won't be using Jupyter notebooks or
anaconda or any other IDE for the time being.] Type the following code :
print("Hello World!")
print("Hello Again")
Note :
• As on today, One of the best (and only) full-featured, dedicated IDEs for Python is PyCharm.
Website: https://www.jetbrains.com/pycharm/
• Although Jupyter notebooks are more popular among Python for Data Science Developers.
Python does not allow punctuation characters such as @, $, and % within identifiers. Python is a
case sensitive programming language. Thus, Suven and suven are two different identifiers in
Python.
total = var_one + \
var_two + \
var_three
Quotation in Python
Python accepts single ('), double (") and triple (''' or """) quotes to denote string literals, as long
as the same type of quote starts and ends the string.
The triple quotes are used to span the string across multiple lines. For example, all the following
are legal −
word = 'word'
sentence = "This is a sentence."
paragraph = """This is a paragraph. It is
made up of multiple lines and sentences."""
# First comment
print ("Hello, Suven!") # second comment
'''
Following triple-quoted string is also ignored by Python This is a
interpreter and can be used as a multiline comments: multiline
comment.
'''
For example-
print("Now I will count the eggs:")
print(3 + 2 + 1 - 5 + 4 % 2 - 1 / 4 + 6)
Based on the data type of a variable, the interpreter allocates memory and decides what can be
stored in the reserved memory.
del var
del var_a, var_b var1 = 1 #long-int
var2 = 10.5 #float
Python supports three different numerical types −
var3 = 10+5j #complex no.
int (signed integers)
float (floating point real values) print(var1)
complex (complex numbers) print(var2)
print(var3)
#All integers in Python3 are represented as
long integers. Hence, there is no separate
number type as long.
Python Programming(Core+ Advanced) By Rocky Sir 19
Python Strings
Strings in Python are identified as a contiguous set of characters represented in the quotation
marks. Python allows either pair of single or double quotes. Subsets of strings can be taken
using the slice operator ([ ] and [:] ) with indexes starting at 0 to (last-1).
The plus (+) sign is the string concatenation operator and the asterisk (*) is the repetition
operator. For example −
str = 'Python@Suven Consultants'
print(str)
print(str[0])
#[m:n] called slice operator
print(str[2:7])
print(str[2:])
print(str[:8])
print(str * 2)
print(str + " Technology")
The values stored in a list can be accessed using the slice operator ([ ] and [:]) with indexes
starting at 0 in the beginning of the list and working their way to end -1. The plus (+) sign is the
list concatenation operator, and the asterisk (*) is the repetition operator. For example −
list = [ 'scikit', 123 , 2.23, 'suven', 72+3j ]
tinylist = [123, 'Technology']
print(list)
print(list[0])
print(list[1:3])
print(list[2:])
print(tuple)
print(tuple[0])
print(tuple[1:3])
print(tuple[2:])
Dictionaries are enclosed by curly braces ({ }) and values can be assigned and accessed using
square braces ([]). For example −
dict = {}
dict['campus'] = "IIT-B"
dict[400071]= "Chembur"
tinydict={'name':'suven','code':1234,'dept':'IT sales'}
print(dict['campus'])
print(dict[400071])
print(tinydict) #elements of dict are not ordered
print(tinydict.keys())
print(tinydict.values())
1. Arithmetic
Operators
Python programming language assumes any non-zero and non-null values as TRUE, and
any zero or null values as FALSE value. Python programming language provides the following
types of decision-making statements.
for i in change:
print(f"I got {i}")
Similarly we have a simple scraping tool , which can scrap (i.e. find all required details) from
some text file or string.
We will now code a simple mail scrapping tool to get all mail-ids from some string data.
import re
s = """
some text, lets say comments
of linked-in or fb post containing mail-ids
"""
match = re.findall(r'[\w\.-]+@[\w\.-]+', s)
print('\n\n')
for email in match:
print(email)
Python Programming(Core+ Advanced) By Rocky Sir 35
Loop Control Statements
The Loop control statements change the execution from its normal sequence. When the
execution leaves a scope, all automatic objects that were created in that scope are destroyed.
for x in it:
print(x, end=" ")
while True:
try:
print(next(f), end=" ")
except StopIteration:
sys.exit()
Python Programming(Core+ Advanced) By Rocky Sir 38
Coding Exercise : 1
Loop through and print out all even numbers from the numbers list in the same order they are
received. Don't print any numbers that come after 237 in the sequence.
numbers = [ 951, 402, 984, 651, 360, 69, 408, 319, 601, 485, 980, 507, 725, 547, 544, 615, 83,
165, 141, 501, 263,617, 865, 575, 219, 390, 984, 592, 236, 105, 942, 941, 386, 462, 47, 418, 907,
344, 236, 375, 823, 566, 597, 978,328, 615, 953, 345, 399, 162, 758, 219, 918, 237, 412, 566,
826, 248, 866, 950, 626, 949, 687, 217, 815, 67, 104, 58, 512, 24, 892, 894, 767, 553, 81, 379,
843, 831, 445, 742, 717, 958, 609, 842, 451, 688, 753, 854, 685, 93, 857, 440, 380, 126, 721,
328, 753, 470, 743, 527 ]
(a) More than one entry per key is not allowed. This means no duplicate key is allowed. When
duplicate keys are encountered during assignment, the last assignment wins. For example −
dictt = {'Name':'SCTPL','Age':15,'Name':'Suven'}
print(dictt)
(b) Keys must be immutable. This means you can use strings, numbers or tuples as dictionary
keys but something like ['key'] is not allowed.
dict = {['Name']: 'Suven', 'Age': 15}
print("dict['Name']: ", dict['Name'])
#Note: keys should be hash-able. [list] are not hashable
Python Programming(Core+ Advanced) By Rocky Sir 57
imp What’s the Difference between shallow and deep copy ?
1> Shallow copy
a. A shallow copy means constructing a new collection object and then populating it with
references to the child objects found in the original.
b. In essence, a shallow copy is only one level deep. The copying process does not recurse and
therefore won’t create copies of the child objects themselves.
xs = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
ys = list(xs) #Makes a shallow copy. ys refers to same address space
print(ys)
print("--------------------")
xs.append(['new sublist'])
print("xs is : ", xs)
print("ys is : ", ys)
print("--------------------") Shallow copy means
both point to the
xs[1][0] = 'X'
same address space.
print("updated xs is : ", xs)
print("updated ys is : ", ys) Hence updates to xs
print("--------------------") would be seen in ys also.
Copying an object this way walks the whole object tree to create a fully independent clone of
the original object and all of its children.
import copy
xs = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
zs = copy.deepcopy(xs) #all child objects are copied
print("zs is : ", zs)
print("--------------------")
xs[1][0] = 'X'
print("updated xs is : ", xs)
print("zs remains same : ", zs)
2> Complete the below code to get list of all keys and key:value pairs.
dictt = {'Name':'SCTPL','Age':15,'Name':'Suven'}
#-- complete the code , to get following output
6> Type below script to see the difference of Dictionary Keys vs. List Indices.
d = {0: 'a', 1: 'b', 2: 'c', 3: 'd'}
print(d)
What is Tick?
Time intervals are floating-point numbers in units of seconds. Particular instants in time are
expressed in seconds since 12:00am, January 1, 1970(epoch).
There is a popular time module available in Python which provides functions for working
with times, and for converting between representations.
The function time.time() returns the current system time in ticks since 12:00am, January 1,
1970(epoch).
#--The above tuple is equivalent to struct_time structure. This structure has following
attributes −
localtime = time.localtime(time.time())
print ("Local current time :", localtime)
10> Type and run below code, for Getting formatted time. Use asctime()
import time
localtime = time.asctime(time.localtime(time.time()))
print("Local current time :", localtime)
6. Scope of Variables
a> Global variables
b> Local variables
Python Programming(Core+ Advanced) By Rocky Sir 68
We would learn, contd…
7. Concept of a module
8. from...import <name> Statement
9. from...import * Statement
10.Executing Modules as Scripts
11.Locating Modules
12.dir() Function
13.globals() and locals()
14.Packages
15.don't confuse between importing from a package w.r.t importing from a module
16.install packages
def printme(str):
"This prints a passed string into this function"
print(str)
return
printme("hello from Suven")
mylist[2]=50
print("Values after change: ", mylist)
return
mylist = [10,20,30]
seeChanges( mylist )
print("Values outside the function: ", mylist)
This allows you to skip arguments or place them out of order because the Python
interpreter is able to use the keywords provided to match the values with parameters.
For example-
3. Lambda functions have their own local namespace and cannot access variables other than
those in their parameter list and those in the global namespace.
Syntax :
lambda [arg1 [,arg2,.....argn]]:expression
#--code example
sum = lambda arg1, arg2: arg1 + arg2
#--Now you can call sum as a function
print("Value of total : ", sum(12,13))
Python Programming(Core+ Advanced) By Rocky Sir 76
Scope of Variables
All variables in a program may not be accessible at all locations in that program. This depends
on where you have declared a variable.
The scope of a variable determines the portion of the program where you can access a
particular identifier. There are two basic scopes of variables in Python −
Global variables
Local variables
This means that local variables can be accessed only inside the function in which they are
declared, whereas global variables can be accessed throughout the program body by all
functions. When you call a function, the variables declared inside it are brought into scope.
Syntax is
from modname import name1[, name2[, ... nameN]]
This provides an easy way to import all the items from a module into the current namespace;
however, this statement should be used sparingly.
if __name__ == "__main__":
f = fib(100)
print(f)
2>If the module not found, Python then searches each directory in the environment variable
PYTHONPATH.
import sys
print("default path is ", sys.path)
Each package in Python is a directory which MUST contain a special file called __init__.py. This
file can be empty, and it indicates that the directory it contains is a Python package, so it can be
imported the same way a module can be imported.
Follow these simple steps to make a package:
1> make a folder recruitment
2> code some .py files in it
3> code a empty __init__.py file and place it in the package
4> 2 ways to : use the package by writing
#-- This is the first way ----
#-- sctpl.py --
from recruitment import interview_prep
from recruitment import first_call
interview_prep.interviewprep()
first_call.firstcall()
recruitment.interview_prep.interviewprep()
recruitment.first_call.firstcall()
import re
# sample output
As a programmer, you can largely just ignore it. All it does is make your program start a little
faster. When your scripts change, they will be recompiled, and if you delete the files or the
whole folder and run your program again, they will reappear.
Before you can read or write a file, you have to open it using Python's built-in open() function.
syntax of open()
file object = open(file_name [, access_mode][, buffering])
access_mode − The access_mode determines the mode in which the file has to be opened,
i.e., read, write, append, etc.
syntax of close()
fileObject.close();
r
Opens a file for reading only. The file pointer is placed at the
beginning of the file. This is the default mode.
rb
Opens a file for reading only in binary format. The file pointer is
placed at the beginning of the file. This is the default mode.
r+
Opens a file for both reading and writing. The file pointer placed at
the beginning of the file.
rb+
Opens a file for both reading and writing in binary format. The file
pointer placed at the beginning of the file.
wb
Opens a file for writing only in binary format. Overwrites the file if
the file exists. If the file does not exist, creates a new file for
writing.
w+
Opens a file for both writing and reading. Overwrites the existing file
if the file exists. If the file does not exist, creates a new file for
reading and writing.
wb+
Opens a file for both writing and reading in binary format. Overwrites
the existing file if the file exists. If the file does not exist,
creates a new file for reading and writing.
ab
Opens a file for appending in binary format. The file pointer is at the
end of the file if the file exists. That is, the file is in the append
mode. If the file does not exist, it creates a new file for writing.
a+
Opens a file for both appending and reading. The file pointer is at the
end of the file if the file exists. The file opens in the append mode.
If the file does not exist, it creates a new file for reading and
writing.
ab+
Opens a file for both appending and reading in binary format. The file
pointer is at the end of the file if the file exists. The file opens in
the append mode. If the file does not exist, it creates a new file for
reading and writing.
Python Programming(Core+ Advanced) By Rocky Sir 95
The file Object Attributes
Once a file is opened and you have one file object, you can get various information related to
that file.
The seek(offset[, from]) method changes the current file position. The offset argument
indicates the number of bytes to be moved. The from argument specifies the reference position
from where the bytes are to be moved.
#Opens a file
fptr = open("test.txt", "r+")
str = fptr.read(5)
print("Read String is : ", str)
To use this module, you need to import it first and then you can call any related functions.
Syntax
os.rename(current_file_name, new_file_name)
Syntax
os.remove(file_name)
import os
from os.path import exists
#delete a file
filename = "suven/test2.txt"
os.remove(filename)
print("test2.txt existence :", exists(filename))
Syntax
os.mkdir("newdir")
Syntax
os.chdir("newdir")
Syntax
os.getcwd()
Syntax
os.rmdir('dirname')
Python Programming(Core+ Advanced) By Rocky Sir 104
Coding Exercise 2:
Write a script to do the following
1> create a directory "test" (only if it does not exist).
2> create a file inside the directory.
Coding Exercise 3:
#--this is version 2 of the above program
Write a script to do the following
1> create a directory "test" (only if it does not exist).
2> change the path to the new directory.
3> create a file inside the (above specified) directory.
Assertions
Programmers often place assertions at the start of a function to check for valid input, and
after a function call to check for valid output.
Syntax
assert Expression[, Arguments]
def KelvinToFahrenheit(Temperature):
assert(Temperature >= 0),"Colder than absolute zero!"
return((Temperature-273)*1.8)+32
print(KelvinToFahrenheit(-5))
Handling an exception
If you have some suspicious code that may raise an exception, you can defend your program by
placing the suspicious code in a try: block. After the try: block, include an except:
statement, followed by a block of code which handles the problem as elegantly as possible.
Syntax try:
#You do your operations here
......................
except Exception-1:
#If there is Exception-1, then execute this block.
except Exception-2:
#If there is Exception-2, then execute this block.
......................
else:
#If there is no exception then execute this block.
Python Programming(Core+ Advanced) By Rocky Sir 110
The except Clause with No Exceptions
try:
#You do your operations here
......................
except:
#if there is any Exception, then execute this block.
else:
#if there is no exception then execute this block.
finally:
#This would always be executed.
......................
Note : You can use a finally: block along with a try: block. The finally: block is a place to
put any code that must execute, whether the try-block raised an exception or not.
Important Pointers:
1> can provide except clause(s), or a finally clause, but
not both.
2> cannot use else clause along with a finally clause.
def temp_convert(var):
try:
return int(var)
except ValueError as A:
print("The argument does not contain numbers\n", A)
ans = temp_convert("sctpl")
print(ans)
def functionName(level):
if level<1:
raise Exception(level)
return level
try:
l = functionName(-10)
print ("level = ",l)
except Exception as e:
print("error in level argument", e.args[0])
exception Exception
All built-in, non-system-exiting exceptions are derived from this class. All user-defined
exceptions should also be derived from this class.
exception ArithmeticError
The base class for those built-in exceptions that are raised for various arithmetic errors:
OverflowError, ZeroDivisionError, FloatingPointError.
exception BufferError
Raised when a buffer related operation cannot be performed.
exception LookupError
The base class for the exceptions that are raised when a key or index used on a mapping or
sequence is invalid: IndexError, KeyError.
exception EOFError
Raised when the input() function hits an end-of-file condition (EOF) without reading any
data.
exception ImportError
Raised when the import statement has trouble trying to load a module. Also raised when
the "from list" in from ... import has a name that cannot be found.
exception ModuleNotFoundError
A subclass of ImportError which is raised by import when a module could not be located.
It is also raised when None is found in sys.modules.
Python Programming(Core+ Advanced) By Rocky Sir 118
exception IndexError
Raised when a sequence subscript is out of range. (Slice indices are silently truncated to
fall in the allowed range; if an index is not an integer, TypeError is raised.)
exception KeyError
Raised when a mapping (dictionary) key is not found in the set of existing keys.
exception KeyboardInterrupt
Raised when the user hits the interrupt key (normally Control-C or Delete). During
execution, a check for interrupts is made regularly. The exception inherits from
BaseException so as to not be accidentally caught by code that catches Exception and thus
prevent the interpreter from exiting.
exception MemoryError
Raised when an operation runs out of memory but the situation may still be rescued (by
deleting some objects). The associated value is a string indicating what kind of (internal)
operation ran out of memory. Note that because of the underlying memory management
architecture (C’s malloc() function), the interpreter may not always be able to completely
recover from this situation; it nevertheless raises an exception so that a stack traceback
can be printed, in case a run-away program was the cause.
exception NotImplementedError
This exception is derived from RuntimeError. In user defined base classes, abstract methods
should raise this exception when they require derived classes to override the method, or while
the class is being developed to indicate that the real implementation still needs to be added.
Note It should not be used to indicate that an operator or method is not meant to be supported
at all – in that case either leave the operator / method undefined or, if a subclass, set it to None.
exception OverflowError
Raised when the result of an arithmetic operation is too large to be represented. This cannot
occur for integers (which would rather raise MemoryError than give up).
exception RecursionError
This exception is derived from RuntimeError. It is raised when the interpreter detects that the
maximum recursion depth (see sys.getrecursionlimit()) is exceeded.
exception RuntimeError
Raised when an error is detected that doesn’t fall in any of the other categories. The associated
value is a string indicating what precisely went wrong.
exception StopIteration
Raised by built-in function next() and an iterator’s __next__() method to signal that there are no
further items produced by the iterator.
Changed in version 3.7: for all code by default: a StopIteration error raised in a generator is
transformed into a RuntimeError.
exception SyntaxError
Raised when the parser encounters a syntax error. This may occur in an import statement, in a
call to the built-in functions exec() or eval(), or when reading the initial script or standard input
(also interactively). Instances of this class have attributes filename, lineno, offset and text for
easier access to the details. str() of the exception instance returns only the message.
exception TabError
Raised when indentation contains an inconsistent use of tabs and spaces. This is a subclass of
IndentationError.
exception SystemExit
This exception is raised by the sys.exit() function. It inherits from BaseException instead of
Exception so that it is not accidentally caught by code that catches Exception. This allows the
exception to properly propagate up and cause the interpreter to exit. When it is not handled,
the Python interpreter exits; no stack traceback is printed.
exception TypeError
Raised when an operation or function is applied to an object of inappropriate type. The
associated value is a string giving details about the type mismatch.
exception ValueError
Raised when an operation or function receives an argument that has the right type but an
inappropriate value, and the situation is not described by a more precise exception such as
IndexError.
Extra reading
Exception hierarchy : https://docs.python.org/3.6/library/exceptions.html
num_key_words = 0
key_word = "scraping"
try:
Regular expressions go one step further: They allow you to specify a pattern of text to search for.
You may not know a business's exact phone number, but if you live in India, you know it will be
two/three digits of state code , followed by a hyphen or space, and then eight more digits.
This is how you, as a human, know a phone number when you see it: 022-25277413 is a phone
number, but 2,225,277,413 is not.
def isPhoneNumber(text):
if len(text) != 13:
return False
import re
phoneNumRegex = re.compile(r'\d\d\d-\d\d\d\d-\d\d\d\d')
mo = phoneNumRegex.search('My number is 022-2527-7413.')
#return value of search is match_object or NONE
if mo :
print('Phone number found: ' + mo.group())
if mo :
print('State code is : ' + mo.group(1))
print('And the number is : ' + mo.group(2))
print('and the entire no. is : ', mo.group())
For example, the regular expression r'Batman|Tina Fey' will match either 'Batman' or
'Tina Fey'.
When both Batman and Tina Fey occur in the searched string, the first occurrence of
matching text will be returned as the Match object.
The ? character flags the group that precedes it as an optional part of the pattern.
Note : If you need to match an actual star character, prefix the star in the regular
expression with a backslash, \*.
Python Programming(Core+ Advanced) By Rocky Sir 136
Matching One or More with the Plus
While * means “match zero or more,” the + (or plus) means “match one or more.” Unlike
the star, which does not require its group to appear in the matched string, the group
preceding a plus must appear at least once. It is not optional.
For example, the regex (Ha){3} will match the string 'HaHaHa', but it will not match 'HaHa',
since the latter has only two repeats of the (Ha) group.
Instead of one number, you can specify a range by writing a minimum, a comma, and a
maximum in between the curly brackets. For example, the regex (Ha){3,5} will match 'HaHaHa',
'HaHaHaHa', and 'HaHaHaHaHa'.
Python’s regular expressions are greedy by default, which means that in ambiguous situations
they will match the longest string possible. The nongreedy version of the curly brackets, which
matches the shortest string possible, has the closing curly bracket followed by a question mark.
While search() will return a Match object of the first matched text in the searched string, the
findall() method will return the strings of every match in the searched string.
If there are groups in the regular expression, then findall() will return a list of tuples. Each tuple
represents a found match, and its items are the matched strings for each group in the regex.
Character classes are nice for shortening regular expressions. The character class [0-5] will
match only the numbers 0 to 5; this is much shorter than typing (0|1|2|3|4|5).
You can define your own character class using square brackets. For example, the character class
[aeiouAEIOU] will match any vowel, both lowercase and uppercase. Enter the following into the
interactive shell:
Coding Exercise : 2
Find all letters other than vowels. Using ^ makes a negative character class.
import re
#your code here
import re
beginsWithHello = re.compile(r'^Hello')
mo1 = beginsWithHello.search('Hello world!')
if mo1 :
print(mo1)
import re
endsWithNumber = re.compile(r'\d$')
import re
wholeStringIsNum = re.compile(r'^\d+$')
#check '1234567890'
#check '12345xyz67890'
Remember that the dot character means “any single character except the newline,” and the
star character means “zero or more of the preceding character.”
if mo :
print(mo.group(1))
print(mo.group(2))
nongreedyRegex = re.compile(r'<.*?>')
mo1 = nongreedyRegex.search('<To serve paneer> for dinner.>')
if mo1 :
print(mo1.group())
greedyRegex = re.compile(r'<.*>')
mo2 = greedyRegex.search('<To serve paneer> for dinner.>')
if mo2 :
print(mo2.group())
import re
The second is the string for the regular expression. The sub() method returns
a string with the substitutions applied.
For example, say you want to censor the names of the secret agents by showing just the first
letters of their names. To do this, you could use the regex Agent (\w)\w* and pass
r'\1****' as the first argument to sub().
The \1 in that string will be replaced by whatever text was matched by group 1— that is, the
(\w) group of the regular expression.
Run the above code “Hide the names of agents” as given in your workspace
The phone number separator character can be a space (\s), hyphen (-), or period (.), so
these parts should also be joined by pipes.
The last part is an optional extension made up of any number of spaces followed by ext, x,
or ext., followed by two to five digits.
The webbrowser module’s open() function can launch a new browser to a specified
URL.
import webbrowser
webbrowser.open('https://suvenconsultants.com//')
if len(sys.argv) > 1:
#--Get address from command line.
The requests module doesn’t come with Python, so you’ll have to install it first. From the
command line, run
pip install requests.
if res.status_code == requests.codes.ok :
len(res.text)
print(res.text[:251])
You can tell that the request for this web page succeeded by checking the status_code attribute
of the Response object. If it is equal to the value of requests.codes.ok, then everything went
fine well. (other status code is 404 called “Not Found.”)
If the request succeeded, the downloaded web page is stored as a string in the Response
object’s text variable. This variable holds a large string of len(res.text).
This will raise an exception if there was an error downloading the file and will do nothing if the
download succeeded.
import requests
res = requests.get('http://suven.net/no_page.html')
try:
res.raise_for_status()
except Exception as exc:
print('There was a problem: %s' % (exc))
Note : Always call raise_for_status() after calling requests.get(). You want to be sure that
the download has actually worked before your program continues.
For review, here’s the complete process for downloading and saving a file:
1. Call requests.get() to download the file.
2. Call open() with 'wb' to create a new file in write binary mode.
3. Loop over the Response object’s iter_content() method.
4. Call write() on each iteration to write the content to the file.
5. Call close() to close the file.
While beautifulsoup4 is the name used for installation, to import Beautiful Soup you run
import bs4.
Coding Exercise:
Scrape a web page and find all <a> tags
I search Google often enough that this workflow—opening my browser, searching for a topic,
and middle-clicking several links one by one—is tedious. It would be nice if I could simply type a
search term on the command line and have my computer automatically open a browser with all
the top search results in new tabs.
Algorithm :
1> Get search keywords from the command line arguments.
2> Retrieves the search results page.
3> Open a browser tab for each result.
5. The text in a Word document is more than just a string. It has font, size, color, and
other styling information associated with it. A style in Word is a collection of these
attributes.
6. A Run object is a contiguous run of text with the same style.
7. A new Run object is needed whenever the text style changes.
With Python-Docx, your Python programs will now be able to read the text from
a .docx file and use it just like any other string value.
You can give both Paragraph and Run objects styles by setting their style attribute to a string.
This string should be the name of a style. If style is set to None, then there will be no style
associated with the Paragraph or Run object.
The string values for the default Word styles are as follows:
When using a linked style for a Run object, you will need to add 'Char' to the end of its name.
For example, to set the Quote linked style for a Paragraph object, you would use
paragraphObj.style = 'Quote', but for a Run object, you would use runObj.style = 'QuoteChar'.
Run Attributes
Runs can be further styled using text
attributes. Each attribute can be set to one
of three values: True (the attribute is always
enabled, no matter what other styles are
applied to the run), False (the attribute is
always disabled), or None (defaults to
whatever the run’s style is set to).
To create your own .docx file, call docx.Document() to return a new, blank Word
Document object. The add_paragraph() document method adds a new paragraph of
text to the document and returns a reference to the Paragraph object that was added.
When you’re done adding text, pass a filename string to the save() document method to
save the Document object to a file.
This will create a file named helloworld.docx in the current working directory
Note that the text This text is being added to the second paragraph. was added to the
Paragraph object in paraObj1, which was the second paragraph added to doc. The
add_paragraph() and add_run() functions return paragraph and Run objects,
respectively, to save you the trouble of extracting them as a separate step.
Keep in mind that as of Python-Docx, new Paragraph objects can be added only to
the end of the document, and new Run objects can be added only to the end of a
Paragraph object. The save() method can be called again to save the additional
changes you’ve made.
Python Programming(Core+ Advanced) By Rocky Sir 180
Adding Headings
Calling add_heading() adds a paragraph with one of the heading styles.
The arguments to add_heading() are a string of the heading text and an integer from 0
to 4. The integer 0 makes the heading the Title style, which is used for the top of the
document. Integers 1 to 4 are for various heading levels, with 1 being the main heading
and 4 the lowest subheading.
A picture is a shape that can appear in either the text or drawing layer. When it appears in the
text layer it is called an inline shape, or more specifically, an inline picture.
Inline shapes are treated like a big text character (a character glyph). python-docx only supports
inline pictures. We can only add. Not get or remove or process the images.
From workspace :
Refer code that reads text, links, images* from docx using docxpy.
The module we will use to work with PDFs is PyPDF2. To install it, run pip install PyPDF2
from the command line. This module name is case sensitive, so make sure the y is
lowercase and everything else is uppercase.
Note : PyPDF2 does not have a way to extract images, charts, or other media
from PDF documents, but it can extract text and return it as a Python string.
Instead, PyPDF2’s PDF-writing capabilities are limited to copying pages from other
PDFs, rotating pages, overlaying pages, and encrypting files.
For example, you might have the boring task of copying certain data from one spreadsheet and
pasting it into another one. Or you might have to go through thousands of rows and pick
out just a handful of them to make small edits based on some criteria. Or you might have to look
through hundreds of spreadsheets of department budgets, searching for any that are in the red.
These are exactly the sort of boring, mindless spreadsheet tasks that Python can do for you.
2. Each workbook can contain multiple sheets (also called worksheets). The sheet the user is
currently viewing (or last viewed before closing Excel) is called the active sheet.
3. Each sheet has columns (addressed by letters starting at A) and rows (addressed by numbers
starting at 1). A box at a particular column and row is called a cell.
4. Each cell can contain a number or text value. The grid of cells with data makes up a sheet.
wb = openpyxl.load_workbook('suven/example.xlsx')
print("Sheet names : ", wb.get_sheet_names())
sheet = wb.get_sheet_by_name('dummy')
print("Sheet Spec : ", sheet)
print("Title of 3rd sheet :", sheet.title)
anotherSheet = wb.get_active_sheet()
print("Active sheet : ", anotherSheet)
import openpyxl
wb = openpyxl.load_workbook('suven/example.xlsx')
sheet = wb.get_sheet_by_name('Sheet1')
print("-------------------")
Note : You can also get a cell using the sheet’s cell() method and passing integers for its row
and column keyword arguments. The first row or column integer is 1, not 0.
wb = openpyxl.load_workbook('suven/example.xlsx')
sheet = wb.get_sheet_by_name('Sheet1')
print(tuple(sheet['A1':'C3']))
Problem : Say you have a spreadsheet of data from the 2017 US Census and you have the
boring task of going through its thousands of rows to count both the total population and the
number of census tracts* for each country. *Each row represents a single census tract.
Even though Excel can calculate the sum of multiple selected cells, you’d still have to select the
cells for each of the 3,000-plus counties. Even if it takes just a few seconds to calculate a
county’s population by hand, this would take hours to do for the whole spreadsheet.
-----------------------------------------------------------------------------------------
Code a script : that can read from the census spreadsheet file and calculate statistics for
each county. Automate your work to finish within matter of seconds.
#--Refer Algorithm and Implementation steps in workspace file.
CSV and JSON files, on the other hand, are just plaintext files. You can view them in a text editor.
But Python also comes with the special csv and json modules, each providing functions to help
you work with these file formats.
You don’t need to know the JavaScript programming language to use JSON files, but the JSON
format is useful to know because it’s used in many web applications. JSON data looks like :
Remember :
1. The advantage of CSV files is simplicity. CSV files are widely supported by many types of
programs, can be viewed in text editors, and are a straightforward way to represent
spreadsheet data.
2. The CSV format is exactly as advertised: It’s just a text file of comma-separated values.
import csv
exampleFile = open('suven/example.csv')
exampleReader = csv.reader(exampleFile)
exampleData = list(exampleReader)
print(exampleData)
Note 1: You don’t pass a filename string directly to the csv.reader() function.
Note 2: The most direct way to access the values in the Reader object is to convert it to a
plain Python list by passing it to list() . Using list() on this Reader object returns a list of
lists, which you can store in a variable like exampleData.
import csv
exampleFile = open('suven/example.csv')
exampleReader = csv.reader(exampleFile)
exampleData = list(exampleReader)
print(exampleData[0][0], '\n')
print(exampleData[0][1], '\n')
print(exampleData[0][2], '\n')
import csv
outputWriter.writerow(['Suven','Consultants','Python','IBM'])
outputWriter.writerow(['Hello, world!','eggs','bread','tea'])
outputWriter.writerow([1, 2, 3.141592, 4])
outputFile.close()
Accessing an API is the same as accessing any other web page via a URL. The difference is that
the data returned by an API is formatted (with JSON, for example) for machines;
APIs aren’t easy for people to read.
Many websites make their data available in JSON format. Facebook, Twitter, Yahoo, Google,
Tumblr, Wikipedia, Flickr, Data.gov, Reddit, IMDb, Rotten Tomatoes, LinkedIn, and many other
popular sites offer APIs for programs to use. Some of these sites require registration, which is
almost always free.
You’ll have to find documentation for what URLs your program needs to request in order to get
the data you want, as well as the general format of the JSON data structures that are returned.
This documentation should be provided by whatever site is offering the API; if they have
a “Developers” page, look for the documentation there.
JSON cannot represent Python-specific objects, such as File objects, CSV Reader or Writer
objects, Regex objects, or Selenium WebElement objects.
import json
jsonDataAsPythonValue = json.loads(stringOfJsonData)
print(jsonDataAsPythonValue)
import json
stringOfJsonData = json.dumps(pythonValue)
print(stringOfJsonData)
#--De-serialization is the reciprocal process of decoding data that has been stored
or delivered in the JSON standard.
import json
data = {
"president": {
"name": "Ram Nath Kovind",
"native": "Uttar Pradesh"
}
}
import json
data = {
"president": {
"name": "Ram Nath Kovind",
"native": "Uttar Pradesh"
}
}
print(json.dumps(data))
print("--------------------------------")
Coding Steps:
• Join strings in sys.argv to get the location.
• Call requests.get() to download the weather data.
• Call json.loads() to convert the JSON data to a Python data structure.
• Print the weather forecast.
You can also write programs that launch other programs on a schedule by using the sub-process
and threading modules.
The time.time() function returns the number of seconds since that moment as a float value.
This number is called an epoch timestamp.
Epoch timestamps can be used to profile code, that is, measure how long a piece of
code takes to run. If you call time.time() at the beginning of the code block you want to
measure and again at the end, you can subtract the first timestamp from the second to
find the elapsed time between those two calls.
import time
for i in range(3):
print('Tick')
time.sleep(1)
print('Tock')
time.sleep(1)
import datetime
#--present datetime
print(datetime.datetime.now())
The wait() method is like waiting for your friend to finish working on her code before you keep
working on yours. The wait() method will block until the launched process has terminated.
This is helpful if you want your program to pause until the user finishes with the other program.
The return value of wait() is the process’s integer exit code.
#-- Syntax :
class ClassName:
'Optional class documentation string'
class_suite
def displayCount(self):
print("Total Employee %d" % Employee.empCount)
1. The first method __init__() is a special method, which is called class constructor or
initialization method that Python calls when you create a new instance of this class.
2. You declare other class methods like normal functions with the exception that the first
argument to each method is self. Python adds the self argument to the list for you; you do
not need to include it when you call the methods.
@classmethod
def class_method(cls):
print("the class method was called")
__module__ − Module name in which the class is defined. This attribute is "__main__" in
interactive mode.
__bases__ − A possibly empty tuple containing the base classes, in the order of their
occurrence in the base class list.
The child class inherits the attributes of its parent class, and you can use those attributes as if
they were defined in the child class. A child class can also override data members and methods
from the parent.
#--Syntax :
class SubClassName (ParentClass1[, ParentClass2, ...]):
'Optional class documentation string'
class_suite
In a similar way, you can drive a class from multiple parent classes as follows −
class A: # define your class A.....
class B: # define your class B.....
class C(A, B): # subclass of A and B.....
Python Programming(Core+ Advanced) By Rocky Sir 227
Overriding Methods
You can always override your parent class methods. One reason for overriding parent's methods
is that you may want special or different functionality in your subclass.
We know that Python has number of numeric classes for our use.
(Reference : https://docs.python.org/3/library/numeric.html ).
There are times, however, that it would be most appropriate to be able to create data objects
that "look like" fractions.
A fraction such as 3/5 consists of two parts. The top value, known as the numerator, can be any
integer. The bottom value, called the denominator, can be any integer greater than 0 (negative
fractions have a negative numerator).
Although it is possible to create a floating point approximation for any fraction, in this case we
would like to represent the fraction as an exact value.
The operations for the Fraction type will allow a Fraction data object to behave like any other
numeric value. We need to be able to add, subtract, multiply, and divide fractions. We also
want to be able to show fractions using the standard "slash" form, for example 3/5. In addition,
all fraction methods should return results in their lowest terms so that no matter what
computation is performed, we always end up with the most common form.
def __init__(self,top,bottom):
self.num = top
self.den = bottom
myfraction = Fraction(3,5)
def show(self):
print(self.num,"/",self.den)
def __str__(self):
return str(self.num) + "/" + str(self.den)
myfraction = Fraction(2,5)
#--call the show()
myfraction.show()
#--print the object directly. It calls __str__ method
print(myfraction)
def __str__(self):
return str(self.num)+"/"+str(self.den)
x = Fraction(1,3)
y = Fraction(1,3)
print(x == y) #shallow comparison or shallow equality
def __str__(self):
return str(self.num)+"/"+str(self.den)
x = Fraction(1,3)
y = Fraction(1,3)
print(x == y)
Python Programming(Core+ Advanced) By Rocky Sir 233
We can override many other methods for our new Fraction class. Some of the most important
of these are the basic arithmetic operations. We would like to be able to create two Fraction
objects and then add them together using the standard “+” notation. At this point, if we try to
add two fractions, we get the following:
If you look closely at the error, you see that the problem is that the "+" operator does not
understand the Fraction operands. We can fix this by providing the Fraction class with a method
that overrides the addition method. In Python, this method is called __add__ and it requires
two parameters. The first, self, is always needed, and the second represents the other operand
in the expression. For example, would ask the Fraction object f1 to add the
Fraction object f2 to itself. This can be written in the standard notation, f1+f2.
class Fraction:
def __add__(self,otherfraction):
newnum = self.num*otherfraction.den + self.den*otherfraction.num
newden = self.den * otherfraction.den
return Fraction(newnum,newden)
print(f_three)
The addition function returns a new Fraction object with the numerator and denominator
of the sum. We can use this method by writing a standard arithmetic expression involving
fractions, assigning the result of the addition, and then printing our result.
def gcd(m,n):
#--your code here
class Fraction:
#--your code here
def __str__(self):
return 'Vector (%d, %d)' % (self.a, self.b)
v1 = Vector(2,10)
v2 = Vector(5,-2)
print("Addition : ", v1 + v2)
print("Subtraction : ", v1 - v2)
print("Multiplication : ", v1 * v2)
print("Division : ", v1/v2)
Python protects those members by internally changing the name to include the class
name. You can access such attributes as object._className__attrName.
Example
This __del__()
destructor prints
the class name of an
instance that is
about to be
destroyed −
As you can see the Child class is empty, but since it inherits from Parent , Python takes
charge of routing all method calls. So you may use the get_value() method of Child
objects and everything works as expected.
#--after Overriding
#--the Child class actually contains a get_value() method with a
different implementation (the id of the two functions are
different).
2> issubclass(sub, sup) boolean function returns True, if the given subclass sub is
indeed a subclass of the superclass sup.
3> isinstance(obj, Class) boolean function returns True, if obj is an instance of class
Class or is an instance of a subclass of Class
Unlike Java : Here in Python we don't define many methods all with the same name, but
difference in no. of parameters for Overloading !!
Remember : You can't have two methods with the same name in Python.
ob=A()
ob.stackoverflow(2)
Coding Exercise : 2:
Correctly overload above stackoverflow() method in 2 ways.
#--example : OL1
#Adds the two numbers
print(1 + 2)
to find :
a> len of the String
b> string representation of the object
c> representing the Object as Boolean : True or False
d> Making Your Objects Capable of Being Added Using +
class A:
def m(self):
print("m of A called")
class B(A):
def m(self):
print("m of B called")
class C(A):
def m(self):
print("m of C called") Coding Exercise : 4:
class D(C,B): Try running this code.
pass
Also try
class B(A):
pass
class C(A):
def m(self):
print("m of C called")
class D(B,C):
pass
x = D()
x.m()
Now what would be the o/p and learning on running the following
code ? #-- refer workspace for help
1. Among the core principles of Python's way of doing things there is a rule about having
high-level interfaces to APIs.
2. The Database API (in this case the Oracle API) is one example.
3. Using the cx_Oracle Python module from Computronix, you can take command over
the Oracle query model while maintaining compatibility with Python Database API
Specification v2.0.
This method can accept a single argument - a SQL statement - to be run directly against the
database. Bind variables assigned through the parameters can be specified as a dictionary,
sequence, or a set of keyword arguments. This method returns a list of variable objects if it is a
query, and None when it's not.
cx_Oracle.Cursor.fetchone() Fetches a single tuple from the database or none if no more rows
are available.
Python Programming(Core+ Advanced) By Rocky Sir 266
#--fetch all records
import cx_Oracle
con = cx_Oracle.connect('system/admin123@localhost:1521/XE')
cursor = con.cursor()
cursor.execute('SELECT * from employees_record')
print(cursor.fetchall())
con.close()
import cx_Oracle
con = cx_Oracle.connect('system/admin123@localhost:1521/XE')
cursor = con.cursor()
#--use pprint()
import cx_Oracle
from pprint import pprint
con = cx_Oracle.connect('system/admin123@localhost:1521/XE')
cursor = con.cursor()
import cx_Oracle
from pprint import pprint
con = cx_Oracle.connect('system/admin123@localhost:1521/XE')
cursor = con.cursor()
cursor.execute('SELECT * from employees_record')
Remember : cx_Oracle cursors are iterators. These powerful Python structures let you
iterate over sequences in a natural way that fetches subsequent items on demand only.
Costly database select operations naturally fit into this idea because the data only gets
fetched when needed. Instead of creating or fetching the whole result set, you iterate
until the desired value is found or another condition fulfilled.
Detailed information about data types is available through the description attribute of
cursor objects. The description is a list of 7-item tuples where each tuple consists of a
column name, column type, display size, internal size, precision, scale and whether
null is possible. Note that column information is only accessible for SQL statements
that are queries.
2. Other data types that are not yet handled by cx_Oracle include XMLTYPE
and all complex types.
3. All queries involving columns of unsupported types will currently fail with a
NotSupportedError exception. You need to remove them from queries or
cast to a supported data type.
When run one-by-one, each need to be parsed separately which adds extra overhead to your
application.
By using bind variables you can tell Oracle to parse a query only once.
When using named bind variables you can check the currently assigned ones using the
bindnames() method of the cursor:
#--or
#-----can also give direct values
cursor.execute('SELECT * from employees_record where
department_id= :1 and salary> :2',(100, 10000))
pprint(r.fetchall())
Important Pointers
1> When binding, you can first prepare the statement and then execute None with
changed parameters
2> Any number of executions can be involved for prepared statements.
3> Each time you can execute the preparedStatement with a different bind value
import cx_Oracle
from pprint import pprint
con = cx_Oracle.connect('system/admin123@localhost:1521/XE')
cursor = con.cursor()
import cx_Oracle
from pprint import pprint
cursor = con.cursor()
#---Update a record
import cx_Oracle
cursor = con.cursor()
#---Delete a record
import cx_Oracle
cursor = con.cursor()
6. Coding Exercises
A thread is an entity within a process that can be scheduled for execution. Also, it is the smallest
unit of processing that can be performed in an OS (Operating System).
In simple words, a thread is a sequence of such instructions within a program that can be
executed independently of other code. For simplicity, you can assume that a thread is simply a
subset of a process!
A thread has a beginning, an execution sequence, and a conclusion. It has an instruction pointer
that keeps track of where within its context is it currently running.
1. It can be pre-empted (interrupted).
2. It can temporarily be put on hold (also known as sleeping) while other threads are running -
this is called yielding.
Kernel Threads are a part of the operating system, while the User-space threads are not
implemented in the kernel.
Consider the diagram below to understand how multiple threads exist in memory:
The thread module has been "deprecated" for quite a long time.
Users are encouraged to use the threading module instead.
Hence, in Python 3, the module "thread" is not available anymore.
However, it has been renamed to "_thread" for backwards compatibilities in Python3.
3. threading.enumerate() − Returns a list of all thread objects that are currently active.
In addition to the methods, the threading module has the Thread class that implements
threading. The methods provided by the Thread class are as follows −
def run(self):
print(threading.currentThread())
Note:
# Create new threads What does the no. in the o/p of
thread1 = myThread() currentThread() indicate?
thread2 = myThread()
# Start new Threads That's the actual Id of the thread.
thread1.start()
thread2.start()
def run(self):
#--refer in workspace--
The acquire(blocking) method of the new lock object is used to force the threads to run
synchronously. The optional blocking parameter enables you to control whether the thread
waits to acquire the lock.
If blocking is set to 0, the thread returns immediately with a 0 value if the lock cannot be
acquired and with a 1 if the lock was acquired. If blocking is set to 1, the thread blocks and
wait for the lock to be released.
The release() method of the new lock object is used to release the lock when it is no longer
required.
3. It is created in the unlocked state and has two principal methods - acquire() and
release().
4. The acquire() method locks the Lock and blocks execution until the release()
method in some other co-routine sets it to unlocked.
5. The release() method should only be called in the locked state, it sets the state to
unlocked and returns immediately.
import threading
def print_cube(num):
print("Cube: {}".format(num * num * num))
def print_square(num):
print("Square: {}".format(num * num))
if __name__ == "__main__":
# creating thread
t1 = threading.Thread(target=print_square, args=(10,))
t2 = threading.Thread(target=print_cube, args=(10,))
# starting thread 1
t1.start()
# starting thread 2
t2.start() #--explanation on next slide
if __name__ == "__main__":
# print ID of current process
print("ID of process running main program: {}".format(os.getpid()))
def worker():
"""thread worker function"""
print('Worker')
return
threads = []
for i in range(5):
t = threading.Thread(target=worker)
t.start()
Q1> Is the threads array used in any way in the above program ?
A>
def my_service():
print(threading.currentThread().getName(), 'Starting')
time.sleep(3)
print(threading.currentThread().getName(), 'Exiting')
t = threading.Thread(name='my_service', target=my_service)
w = threading.Thread(name='worker', target=worker)
w2 = threading.Thread(target=worker) # uses default name
w.start()
w2.start()
t.start()
class MyThread(threading.Thread):
def run(self):
print('running')
return
for i in range(5):
t = MyThread()
t.start()
class MyThread(threading.Thread):
def run(self):
print('running')
return
for i in range(5):
t = MyThread()
t.start()
observations : o/p :
Conditions
A Condition object is simply a more advanced version of the Event object. It too acts as
a communicator between threads and can be used to notify() other threads about a change
in the state of the program. For example, it can be used to signal the availability of a
resource for consumption.
Other threads must also acquire() the condition (and thus its related lock) before wait()ing
for the condition to be satisfied.
Also, a thread should release() a Condition once it has completed the related actions, so
that other threads can acquire the condition for their purposes.
<Q6> code demonstrates the implementation of a simple producer-consumer problem
with the help of the Condition object.
observations : o/p :
Suppose we wanted to create a line counter class that takes in a file, reads each line, then
counts the total amount of lines in the file. Using a class, it could look something like the
following:
#--Case 2
lc.read()
#--The lc.lines property has been changed.
#--This is called changing the state of the lc object.
print(lc.lines)
>> [['Hello world!', ...]]
print(lc.count())
>> 100
2. The functions that meet the above criteria are called pure functions.
3. Here’s an example to highlight the difference between pure functions, and non-pure:
# Create a global variable `A`.
A = 5
def impure_sum(b):
# Adds two numbers, but uses the global `A` variable.
return b + A
def pure_sum(a, b):
# Adds two numbers, using ONLY the local function inputs.
return a + b
1. The benefit of using pure functions
print(impure_sum(6)) over impure (non-pure) functions is the
>> 11 reduction of side effects.
2. Side effects occur when there are
print(pure_sum(4, 6)) changes performed within a function’s
>> 10 operation that are outside its scope.
There are a set of important first-class functions that are commonly used within the functional
paradigm. These functions take in a Python iterable, and, like sorted(), apply a function for each
element in the list.