13  Module 2 - Day 2

Topics

For today’s practice make use of notebook module2-day2.ipynb created in your enviroment. Shut down kernel for all previous notebooks (if in runing condition) by right cliking on notbeook on left hand side file browser.

13.1 Reading files

!cat poem.txt
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
with open("poem.txt") as filehandle: 
    text = filehandle.read()
print(text)
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
with open("poem.txt") as f:
    print(f.readline(), end="")
The Zen of Python, by Tim Peters
f = open("poem.txt") 
f.readline()
'The Zen of Python, by Tim Peters\n'
f
<_io.TextIOWrapper name='poem.txt' mode='r' encoding='UTF-8'>
next(f)
'\n'
next(f)
'Beautiful is better than ugly.\n'
f.readline()
'Explicit is better than implicit.\n'
for line in f: # this loop will readinf file from where the erlier poiter left!
    print(line, end="")
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
f.close()
def printfile_with_linunums(filename):
    with open(filename) as f:
        for linenum, line in enumerate(f, start=1):
            print(linenum, line)
printfile_with_linunums("poem.txt")
1 The Zen of Python, by Tim Peters

2 

3 Beautiful is better than ugly.

4 Explicit is better than implicit.

5 Simple is better than complex.

6 Complex is better than complicated.

7 Flat is better than nested.

8 Sparse is better than dense.

9 Readability counts.

10 Special cases aren't special enough to break the rules.

11 Although practicality beats purity.

12 Errors should never pass silently.

13 Unless explicitly silenced.

14 In the face of ambiguity, refuse the temptation to guess.

15 There should be one-- and preferably only one --obvious way to do it.

16 Although that way may not be obvious at first unless you're Dutch.

17 Now is better than never.

18 Although never is often better than *right* now.

19 If the implementation is hard to explain, it's a bad idea.

20 If the implementation is easy to explain, it may be a good idea.

21 Namespaces are one honking great idea -- let's do more of those!
def printfile_with_linunums(filename):
    with open(filename) as f:
        for linenum, line in enumerate(f, start=1):
            print(linenum, line, end="")
printfile_with_linunums("poem.txt")
1 The Zen of Python, by Tim Peters
2 
3 Beautiful is better than ugly.
4 Explicit is better than implicit.
5 Simple is better than complex.
6 Complex is better than complicated.
7 Flat is better than nested.
8 Sparse is better than dense.
9 Readability counts.
10 Special cases aren't special enough to break the rules.
11 Although practicality beats purity.
12 Errors should never pass silently.
13 Unless explicitly silenced.
14 In the face of ambiguity, refuse the temptation to guess.
15 There should be one-- and preferably only one --obvious way to do it.
16 Although that way may not be obvious at first unless you're Dutch.
17 Now is better than never.
18 Although never is often better than *right* now.
19 If the implementation is hard to explain, it's a bad idea.
20 If the implementation is easy to explain, it may be a good idea.
21 Namespaces are one honking great idea -- let's do more of those!
%load_problem cat
Problem: Cat

Write a program cat.py that takes one or more filenames are command-line arguments and prints the contents of them.

$ python cat.py files/five.txt
one
two
three
four
five

$ python cat.py files/abcd.txt files/1234.txt
A
B
C
D
1
2
3
4

You can verify your solution using:

%verify_problem cat

%%file cat.py
# your code here


%%file multiply.py
import sys

print(sys.argv)
Writing multiply.py
!python multiply.py 5 3 sds hghg 
['multiply.py', '5', '3', 'sds', 'hghg']
%%file multiply.py
import sys

a = float(sys.argv[1])
b = float(sys.argv[2])

print(a*b)
Overwriting multiply.py
!python multiply.py 45 2
90.0
!python cat.py poem.txt hello.txt
%%file args.py
import sys

print(sys.argv)
Overwriting args.py
!python args.py hello python how are you
['args.py', 'hello', 'python', 'how', 'are', 'you']
!python args.py "hello python how are you"
['args.py', 'hello python how are you']
 %load_problem grep
Problem: Grep Command

Implement Unix command grep in Python.

Write a program grep.py that takes a pattern and a file as command-line arguments and print all the lines in the file that contain that pattern.

The pattern could be any text and there is no need to support regular expressions.

$ cat files/zen-of-python.txt
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

$ python grep.py never files/zen-of-python.txt
Errors should never pass silently.
Now is better than never.
Although never is often better than *right* now.

$ grep the files/zen-of-python.txt
Special cases aren't special enough to break the rules.
In the face of ambiguity, refuse the temptation to guess.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.

You can verify your solution using:

%verify_problem grep

%%file grep.py
# your code here


!python args.py poem.txt hello.txt
['args.py', 'poem.txt', 'hello.txt']
args = ['args.py', 'poem.txt', 'hello.txt']
str(args)
"['args.py', 'poem.txt', 'hello.txt']"
args
['args.py', 'poem.txt', 'hello.txt']
for f in args:
    print(f)
args.py
poem.txt
hello.txt
%%file a_cat.py
# your code here
import sys


def print_file(file):
    with open(file) as f:
        for i,l in enumerate(f,start=1):
            print(i,l,end="")



def print_files(files):
    for file in files:
        print_file(file)


k = sys.argv[1:] # multiple files
f = sys.argv[1] # single element 
print_files(k)
Writing a_cat.py
!python a_cat.py poem.txt hello.txt
1 The Zen of Python, by Tim Peters
2 
3 Beautiful is better than ugly.
4 Explicit is better than implicit.
5 Simple is better than complex.
6 Complex is better than complicated.
7 Flat is better than nested.
8 Sparse is better than dense.
9 Readability counts.
10 Special cases aren't special enough to break the rules.
11 Although practicality beats purity.
12 Errors should never pass silently.
13 Unless explicitly silenced.
14 In the face of ambiguity, refuse the temptation to guess.
15 There should be one-- and preferably only one --obvious way to do it.
16 Although that way may not be obvious at first unless you're Dutch.
17 Now is better than never.
18 Although never is often better than *right* now.
19 If the implementation is hard to explain, it's a bad idea.
20 If the implementation is easy to explain, it may be a good idea.
21 Namespaces are one honking great idea -- let's do more of those!
1 hello
2 welcome
3 namaskar
%%file grep.py
import sys
def word_found(filename,word):
    with open (filename) as f:
        content = f.read()
        for line in content:
            if word in line:
                print(line)
word_found(sys.argv[1],sys.argv[2]) 

13.1.1 different modes to open files

Here are different modes in which file can be opened::

  ================   ============================================
  mode               meaning
  ================   ============================================
  no mode given      open file in text mode for reading
  "w"                open file to write. if file exists, overrite
  "a"                open file to append. if file exists, append
  "rb" or  "b"       open file to read bibary
  "wb"               open file in write mode to write binary.
  "ab"               open file in bibary and append mode
  ================   ============================================
stocks = [{"name":"IBM", "open":123, "high":126, "low": 120, "close":123.5},
         {"name":"APPLE", "open":121, "high":126, "low": 120, "close":123.5},
         {"name":"AT&T", "open":123, "high":126, "low": 120, "close":123.5}]
with open("digits.txt", "w") as f:
    f.write("one")
    f.write("two")
!python cat.py digits.txt
onetwo
with open("digits.txt", "w") as f:
    f.write("one")
    f.write("\n")
    f.write("two")
!python cat.py digits.txt
one
two

with open("stocks.csv", "w") as f:
    header = ",".join(list(stocks[0].keys()))
    f.write(header)
    f.write("\n")
    for st in stocks:
        row = ",".join(list(st.values()))
        f.write(row)
        f.write("\n")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[45], line 6
      4 f.write("\n")
      5 for st in stocks:
----> 6     row = ",".join(list(st.values()))
      7     f.write(row)
      8     f.write("\n")

TypeError: sequence item 1: expected str instance, int found
",".join([12, 34, 34, 54])
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[47], line 1
----> 1 ",".join([12, 34, 34, 54])

TypeError: sequence item 0: expected str instance, int found

with open("stocks.csv", "w") as f:
    header = ",".join(list(stocks[0].keys()))
    f.write(header)
    f.write("\n")
    for st in stocks:
        row = ",".join([str(v) for v in st.values()])
        f.write(row)
        f.write("\n")
!python cat.py stocks.csv
name,open,high,low,close
IBM,123,126,120,123.5
APPLE,121,126,120,123.5
AT&T,123,126,120,123.5
nums = [12, 23, 43, 454, 56]
strnums = []
for n in nums:
    strnums.append(str(n))
[str(n) for n in nums]
['12', '23', '43', '454', '56']
%%file multiply_many.py
import sys
def product(nums):
    p = 1
    for n in nums:
        p = p * n
    return p
    
if __name__ == "__main__": # dunder
    nums = [float(n) for n in sys.argv[1:]]
    print(product(nums))
Overwriting multiply_many.py
!python multiply_many.py 23 12 23 1 2 4
50784.0
!python multiply_many.py 12 5
60.0
import multiply_many
!python a_cat.py poem.txt
1 The Zen of Python, by Tim Peters
2 
3 Beautiful is better than ugly.
4 Explicit is better than implicit.
5 Simple is better than complex.
6 Complex is better than complicated.
7 Flat is better than nested.
8 Sparse is better than dense.
9 Readability counts.
10 Special cases aren't special enough to break the rules.
11 Although practicality beats purity.
12 Errors should never pass silently.
13 Unless explicitly silenced.
14 In the face of ambiguity, refuse the temptation to guess.
15 There should be one-- and preferably only one --obvious way to do it.
16 Although that way may not be obvious at first unless you're Dutch.
17 Now is better than never.
18 Although never is often better than *right* now.
19 If the implementation is hard to explain, it's a bad idea.
20 If the implementation is easy to explain, it may be a good idea.
21 Namespaces are one honking great idea -- let's do more of those!
import a_cat
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
Cell In[61], line 1
----> 1 import a_cat

File /opt/arcesium-finop-25/website/live-notes/a_cat.py:18
     14         print_file(file)
     17 k=sys.argv[1:]
---> 18 print_files(k)

File /opt/arcesium-finop-25/website/live-notes/a_cat.py:14, in print_files(files)
     12 def print_files(files):
     13     for file in files:
---> 14         print_file(file)

File /opt/arcesium-finop-25/website/live-notes/a_cat.py:6, in print_file(file)
      5 def print_file(file):
----> 6     with open(file) as f:
      7         for i,l in enumerate(f,start=1):
      8             print(i,l,end="")

FileNotFoundError: [Errno 2] No such file or directory: '-f'
sys.argv
['/opt/tljh/user/lib/python3.12/site-packages/ipykernel_launcher.py',
 '-f',
 '/home/jupyter-vikrant/.local/share/jupyter/runtime/kernel-eadd8f89-1e0d-4eb6-8e7e-052e78621fe2.json']
!python cat.py digits.txt
one
two
with open("digits.txt", "a") as f:
    f.write("three")
    f.write("\n")
    f.write("four")
    f.write("\n")
!python cat.py digits.txt
one
twothree
four
!python cat.py stocks.csv
name,open,high,low,close
IBM,123,126,120,123.5
APPLE,121,126,120,123.5
AT&T,123,126,120,123.5

13.1.2 parsing

The process of loading text data into usable python data structure is called as parsing

def parse_csv(csvfile):
    with open(csvfile) as f:
        data = []
        for line in f:
            l = line.strip() # remove trailing spaces/new line charecter
            tokens = l.split(",")
            data.append(tokens)
    return data
"name,open,high,low,close"
stocksdata = parse_csv("stocks.csv")
stocksdata[0]
['name', 'open', 'high', 'low', 'close']
stocksdata[1:]
[['IBM', '123', '126', '120', '123.5'],
 ['APPLE', '121', '126', '120', '123.5'],
 ['AT&T', '123', '126', '120', '123.5']]
def parse_csv(csvfile):
    with open(csvfile) as f:
        data = []
        for line in f:
            l = line.strip() # remove trailing spaces/new line charecter
            tokens = l.split(",")
            data.append(tokens)
    return data

def data_convert(data):
    converters = [str, float, float, float, float]
    newdata = []
    for row in data:
        newrow = []
        for v, func in zip(row, converters):
            newrow.append(func(v))
        newdata.append(newrow)
    return newdata
stocksdata
[['name', 'open', 'high', 'low', 'close'],
 ['IBM', '123', '126', '120', '123.5'],
 ['APPLE', '121', '126', '120', '123.5'],
 ['AT&T', '123', '126', '120', '123.5']]
for row in stocksdata:
    print(row)
['name', 'open', 'high', 'low', 'close']
['IBM', '123', '126', '120', '123.5']
['APPLE', '121', '126', '120', '123.5']
['AT&T', '123', '126', '120', '123.5']
['IBM', '123', '126', '120', '123.5']
[str, float, float, float, float] 
data_convert(stocksdata[1:])
[['IBM', 123.0, 126.0, 120.0, 123.5],
 ['APPLE', 121.0, 126.0, 120.0, 123.5],
 ['AT&T', 123.0, 126.0, 120.0, 123.5]]
def parse_csv(csvfile):
    with open(csvfile) as f:
        return [line.strip().split(",") for line in f]

def data_convert(data):
    converters = [str, float, float, float, float]
    newdata = []
    for row in data:
        newrow = [func(v) for v, func in zip(row, converters)]
        newdata.append(newrow)
    return newdata
!cat hello.txt
hello
welcome
namaskar
def parse_csv_raw(csvfile):
    with open(csvfile) as f:
        return [line.strip().split(",") for line in f]

def data_convert(data):
    converters = [str, float, float, float, float]
    newdata = []
    for row in data:
        newrow = [func(v) for v, func in zip(row, converters)]
        newdata.append(newrow)
    return newdata

def parse_csv(csvfile):
    data = parse_csv_raw(csvfile)
    headers = data[0]
    rest = data[1:]
    rest = data_convert(rest)
    return [headers] + rest
parse_csv("stocks.csv")
[['name', 'open', 'high', 'low', 'close'],
 ['IBM', 123.0, 126.0, 120.0, 123.5],
 ['APPLE', 121.0, 126.0, 120.0, 123.5],
 ['AT&T', 123.0, 126.0, 120.0, 123.5]]

13.2 String formating

String formating is very usefull for templating!

msg = """
Hi {user},

Welcome to the Python Training program!
Your login credentials for accessing the lab server (used throughout the training starting Wednesday, 10 Dec 2025) are below:

Username: {username}
Password: {password}

Please use these credentials to log in to the lab environment:

Lab Portal: https://lab.finop-25.arcesium.vikrant.dev/

You can find the full training schedule, materials, and other details here:

Training Website: https://finop-25.arcesium.vikrant.dev/

If you have any trouble accessing the portal, feel free to reach out.

Regards,
Vikrant"""
final_msg = msg.format(user="Vikrant Patil", username="vikrant", password="vikrant12231")
print(final_msg)

Hi Vikrant Patil,

Welcome to the Python Training program!
Your login credentials for accessing the lab server (used throughout the training starting Wednesday, 10 Dec 2025) are below:

Username: vikrant
Password: vikrant12231

Please use these credentials to log in to the lab environment:

Lab Portal: https://lab.finop-25.arcesium.vikrant.dev/

You can find the full training schedule, materials, and other details here:

Training Website: https://finop-25.arcesium.vikrant.dev/

If you have any trouble accessing the portal, feel free to reach out.

Regards,
Vikrant
msg
'\nHi {user},\n\nWelcome to the Python Training program!\nYour login credentials for accessing the lab server (used throughout the training starting Wednesday, 10 Dec 2025) are below:\n\nUsername: {username}\nPassword: {password}\n\nPlease use these credentials to log in to the lab environment:\n\nLab Portal: https://lab.finop-25.arcesium.vikrant.dev/\n\nYou can find the full training schedule, materials, and other details here:\n\nTraining Website: https://finop-25.arcesium.vikrant.dev/\n\nIf you have any trouble accessing the portal, feel free to reach out.\n\nRegards,\nVikrant'
"hello the answer to {} of life is {}".format("question", 42)
'hello the answer to question of life is 42'
"I can also have friends like {0} {2} {1}".format("int", "float", "list")
'I can also have friends like int list float'
user = "vikrant"
password = "vikealkjfa8eq"
f"Hello, this is you username:{user} and password: {password}"
'Hello, this is you username:vikrant and password: vikealkjfa8eq'
for i in range(1, 11):
    print(i, i**2, i**3)
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
10 100 1000
for i in range(1, 11):
    print(f"{i:2d} {i**2:3d} {i**3:4d}")
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000
name = "python"
name.center(50)
'                      python                      '
name.rjust(10)
'    python'
name.ljust(10)
'python    '

problem

  • write a fuction triangle to make a triangle of “*”
>>> triangle(4)
     *
    * *
   * * *
  * * * *
def generate_triangle(base, char="*"):
    return [[char]*i for i in range(1, base+1)]
        
    
generate_triangle(5)
[['*'],
 ['*', '*'],
 ['*', '*', '*'],
 ['*', '*', '*', '*'],
 ['*', '*', '*', '*', '*']]
def generate_triangle(base, char="*"):
    return [[char]*i for i in range(1, base+1)]

def pretyprint_tr(triangle):
    n = len(max(triangle, key=len))
    maxsize = n + n-1
    for line in triangle:
        print(" ".join(line).center(maxsize))
t= generate_triangle(8)
pretyprint_tr(t)
       *       
      * *      
     * * *     
    * * * *    
   * * * * *   
  * * * * * *  
 * * * * * * * 
* * * * * * * *
" ".join(["one", "two"])
'one two'