Changes

Jump to: navigation, search

OPS435 Python Lab 5

23,019 bytes added, 04:04, 4 September 2017
Created page with "= LAB OBJECTIVES = This lab will introduce object oriented programming, using classes to create objects, and reading/writing to files. The first investigation will focus on fi..."
= LAB OBJECTIVES =
This lab will introduce object oriented programming, using classes to create objects, and reading/writing to files.
The first investigation will focus on file management, opening files, saving data to files, and reading files. Since many tasks that system administrators deal with files, this is a crucial skill to understand.
The second investigation will cover object oriented programming. Objects are primarily used to store data and code.

== PYTHON REFERENCE ==
As you develop your Python scripting skills, you may start to be "overwhelmed" with the volume of information that you have absorbed over these labs. One way to help, is to write what you have learned in your labs into your notes. Also, in programming, it is important to use online references in order to obtain information regarding Python scripting techniques and tools.
Below is a table with links to useful online Python reference sites (by category). You may find these references useful when performing assignments, etc.

https://docs.python.org/3/tutorial/errors.html
https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files
https://docs.python.org/3/library/functions.html#open
https://docs.python.org/3/tutorial/classes.html
https://docs.python.org/3/library/exceptions.html

= INVESTIGATION 1: Files =
This first investigation will cover the ability to open text files on the system, read the contents, store the contents, and finally write the contents back into a file. This is a very common practice in programming, used in situations such as logging output, logging errors, reading/creating configuration files, temporary files, and more. Files are accessed through the use of file objects, an object is a storage location which stores data in the form of attributes(variables) and methods(functions). Creating our own objects will be covered in investigation 3.

== PART 1 - Reading From Files ==
:'''Perform the Following Steps:'''
::#To start, open the ipython3 shell:<source lang="python">
ipython3
</source>
::#Create a new text file in the lab5 directory:<source lang="python">
%cd ~/ops435/lab5
%vim ~/ops435/lab5/data.txt
</source>
::#Place the following content inside the new file and save it:<source lang="python">
Hello World
This is the second line
Third line
Last line
</source>
::#Now lets write some python code to open this file for reading.<source lang="python">
f = open('data.txt', 'r')
</source>
::#The f is a new variable we are creating to store the file object. The open() function takes two string arguments, a path to a file, and a mode option for reading, writing, appending, etc. The open() function will return a special object to us, this object will allow us to read the lines inside the file. Before we use this object lets inspect it with dir().<source lang="python">
dir(f)
</source>
::#Lets inspect some of the functions we can use on this file object.<source lang="python">
help(f.read) # Reads all lines and stores in a string
help(f.readlines) # Reads all lines and stores in a list
help(f.readline) # Reads first line, if run a second time it will read the second line, then third
help(f.writable)
help(f.close)
f.writable() # Object method (function returns value)
f.name # Object attribute (variable string)
f.closed # Object attribute (variable boolean)
</source>
::#Next read data from the file and close the file to free up resources.<source lang="python">
read_data = f.read()
read_data
</source>
::#Finally close the file to free up the computer resources. First lets check to see if the file is already closed.<source lang="python">
f.closed # This object attribute will give true if the file is closed and false if open
f.close() # This method will close the file
f.closed # Confirm the file is closed
</source>
::#All together the code for reading from a file should look like the following:<source lang="python">
f = open('data.txt', 'r') # Open file
read_data = f.read() # Read from file
f.close() # Close file
f.closed # Confirm file is closed
</source>
::#Another way to read data from a file is using the with statement. The advantage here is that it will automatically close() the file when complete:<source lang="python">
with open('data.txt', 'r') as f: # Open file
read_data = f.read() # Read from file
f.closed # Confirm file is closed
</source>
::#Next lets read the data<source lang="python">
read_data
</source>
::#This displays the data from the file in a single long string. The end of each line in the file will show a '\n' which represents the newline character in a file. Split the line on the new-line characters, so more inspection can be done on a single line at a time.<source lang="python">
dir(read_data)
help(read_data.split)
read_data.split('\n') # Returns a list
list_of_lines = read_data.split('\n') # Saves returned list in variable
list_of_lines
</source>
::#The above works, but it's not the best way to get a list of lines. The man benefit above is that the lines can be split in any way desired(on spaces, on periods, etc). The easiest way to just get a list of all lines can be done using the file object and it's methods.<source lang="python">
f = open('data.txt', 'r')
method1 = list(f)
f.close()
method1
f = open('data.txt', 'r')
method2 = f.readlines()
f.close()
method2
</source>
::#Finally, sometimes all that needs to be done is to print the file to the screen. In these simple cases, there is no need to create extra/large variables to store the data, instead just print it to the screen one line at a time. Doing one of the following methods will save computer resources while reading files.<source lang="python">
f = open('data.txt', 'r')
for line in f:
print(line, end='')
f.close()
</source>
::#The python print() function by default adds the new-line character to the end of the line. Using the end='' argument used in print replaces the '\n' at the end with nothing ''. This allows the print() to use the new-line characters found on each line of the file that was read. Though if desired you can always strip the new-line characters from any lines. The strip() function will remove all leading and trailing whitespace, which may help in processing some lines or data.<source lang="python">
f = open('data.txt', 'r')
for line in f:
print(line.strip())
f.close()
</source>

=== Create a Python Script Demonstrating Reading Files ===
:'''Perform the Following Instructions'''
::#Create the '''~/ops435/lab5/lab5a.py''' script.
::#Use the following as a template:<source lang="python">
#!/usr/bin/env python3

def read_file_string(file_name):
# Takes a filename string, returns a string of all lines in the file

def read_file_list(file_name):
# Takes a filename string, returns a list of lines without new-line characters

if __name__ == '__main__':
file_name = 'data.txt'
print(read_file_string(file_name))
print(read_file_list(file_name))
</source>

:::*The read_file_string() function should return a string
:::*The read_file_list() function should return a list
:::*The read_file_list() function must remove the new-line characters from each line in the list
:::*Both functions must accept one argument which is a string
:::*The script should show the exact output as the samples
:::*The script should contain no errors

::::'''Sample Run 1:'''<source lang="python">
python3 lab5a.py
Hello World
This is the second line
Third line
Last line
['Hello World', 'This is the second line', 'Third line', 'Last line']
</source>

::::'''Sample Run 2 (with import):'''<source lang="python">
import lab5a
file_name = 'data.txt'
lab5a.read_file_string(file_name)
'Hello World\nThis is the second line\nThird line\nLast line\n'
lab5a.read_file_list(file_name)
['Hello World', 'This is the second line', 'Third line', 'Last line']
</source>
:::3. Exit the ipython3 shell, download the checking script and check your work. Enter the following commands from the bash shell.<source lang="bash">
cd ~/ops435/lab5/
pwd #confirm that you are in the right directory
ls CheckLab5.py || wget matrix.senecac.on.ca/~acoatley-willis/CheckLab5.py
python3 ./CheckLab5.py -f -v lab5a
</source>
:::4. Before proceeding, make certain that you identify any and all errors in lab5a.py. When the checking script tells you everything is OK before proceeding to the next step.
<br><br>
== PART 2 - Writing To Files ==
There is a danger involved in this next section, when opening files for writing, Python assumes content in the file is no longer wanted and it's immediately deleted. If the file contents are important, append to the file instead.
:'''Perform the Following Steps:'''
::#To start, open the ipython3 shell:<source lang="python">
ipython3
</source>
::#When opening a file the 'w' option can be give to open(). When 'w' is provided the previous contents inside the file are deleted, this deleting takes place the moment the open() function is executed, not during the write. If the file that is being written to doesn't exit, it will be created.<source lang="python">
f = open('file1.txt', 'w')
</source>
::#To add lines of text to the file, use the write() method for the file object. For safe file management, always end every line with a '\n'. Multiple lines may also be placed inside a single write, simply put the '\n' wherever a line should end.<source lang="python">
f.write('Line 1\nLine 2 is a little longer\nLine 3 is too\n')
</source>
::#Once the write() has been run, the final step would be to close() the file. The file MUST be closed properly or else data will not consistently be written to the file. Not closing a file can lead to corruption or not changes being made. <source lang="python">
f.close()
</source>
::#View the contents of the file to make sure the write data was saved. We can use the ipython bash alias %cat to do this.<source lang="python">
%cat file1.txt
Line 1
Line 2 is a little longer
Line 3 is too
</source>
::#Create another file but this time, run multiple write() methods together. The ability to write() multiple lines like this allows for writes to take place inside loops and more complex programs to continuously write to a file.<source lang="python">
f = open('file2.txt', 'w')
f.write('Line 1\nLine 2 is a little longer\nLine 3 is too\n')
f.write('This is the 4th line\n')
f.write('Last line in file\n')
f.close()
</source>
::#View the contents of the file2.txt to make sure the write data was saved.<source lang="python">
%cat file2.txt
Line 1
Line 2 is a little longer
Line 3 is too
This is the 4th line
Last line in file
</source>
::#View the contents of the file1.txt to make sure it has the original data and has not been changed<source lang="python">
%cat file1.txt
Line 1
Line 2 is a little longer
Line 3 is too
</source>
::#In the event that the data in the file is important and should not be overwritten, we can append data to the end of the file instead. Use the option 'a' instead of 'w' to perform appending.<source lang="python">
f = open('file1.txt', 'a')
f.write('This is the 4th line\n')
f.write('Last line in file\n')
f.close()
</source>
::#The final point to make when writing to files is to make sure that the values being written are strings. This means that before trying to place integers, floats, lists, or dictionaries into a file, first either convert the value using str() or extract the specific strings from items in the list. <source lang="python">
my_number = 1000
my_list = [1,2,3,4,5]
f = open('file3.txt', 'w')
f.write(str(my_number) + '\n')
for num in my_list:
f.write(str(num) + '\n')
f.close()
</source>
::#View the contents of the file3.txt to make sure the write data was saved.<source lang="python">
%cat file3.txt
1000
1
2
3
4
5
</source>
=== Create a Python Script Demonstrating Writing to Files ===
:'''Perform the Following Instructions'''
::#Copy '''~/ops435/lab5/lab5a.py''' script to '''~/ops435/lab5/lab5b.py''' script. We need the previous read functions written.
::#Use the following as a template:<source lang="python">
#!/usr/bin/env python3

def read_file_string(file_name):
# This is the same code from lab5a.py

def read_file_list(file_name):
# This is the same code from lab5a.py

def append_file_string(file_name, string_of_lines):
# Takes two strings, appends the string to the end of the file

def write_file_list(file_name, list_of_lines):
# Takes a string and list, writes all items from list to file where each item is one line

def copy_file_add_line_numbers(file_name_read, file_name_write):
# Takes two strings, reads data from first file, writes data to new file, adds line number to new file

if __name__ == '__main__':
file1 = 'seneca1.txt'
file2 = 'seneca2.txt'
file3 = 'seneca3.txt'
string1 = 'First Line\nSecond Line\nThird Line\n'
list1 = ['Line 1', 'Line 2', 'Line 3']
append_file_string(file1, string1)
print(read_file_string(file1))
write_file_list(file2, list1)
print(read_file_string(file2))
copy_file_add_line_numbers(file2, file3)
print(read_file_string(file3))


</source>

:::'''append_file_string()'''
::::#Takes two string arguments
::::#Appends to the file(Argument 1) all data from the string(Argument 2)
:::'''write_file_list()'''
::::#Takes two arguments, a string and a list
::::#Writes to file(Argument 1) all lines of data found in the list(Argument 2)
:::'''copy_file_add_line_numbers()'''
::::#Takes two arguments, both strings, both filesnames
::::#Reads all data from first file(Argument 1), writes all lines into secon file(Argument 2) adding line numbers
::::#Line numbers should be added to the beginning of each line with a colon next to them(see sample output)
::::#Hint: review len() and range() functions from lab 3 and lab 4

::::'''Sample Run 1:'''<source lang="python">
python3 lab5b.py
First Line
Second Line
Third Line

Line 1
Line 2
Line 3

1:Line 1
2:Line 2
3:Line 3

</source>

::::'''Sample Run 2 (with import):'''<source lang="python">
import lab5b
file1 = 'seneca1.txt'
file2 = 'seneca2.txt'
file3 = 'seneca3.txt'
string1 = 'First Line\nSecond Line\nThird Line\n'
list1 = ['Line 1', 'Line 2', 'Line 3']

lab5b.append_file_string(file1, string1)

lab5b.read_file_string(file1)
'First Line\nSecond Line\nThird Line\nFirst Line\nSecond Line\nThird Line\n'

lab5b.write_file_list(file2, list1)

lab5b.read_file_string(file2)
'Line 1\nLine 2\nLine 3\n'

lab5b.copy_file_add_line_numbers(file2, file3)

lab5b.read_file_string(file3)
'1:Line 1\n2:Line 2\n3:Line 3\n'
</source>

:::3. Exit the ipython3 shell, download the checking script and check your work. Enter the following commands from the bash shell.<source lang="bash">
cd ~/ops435/lab5/
pwd #confirm that you are in the right directory
ls CheckLab5.py || wget matrix.senecac.on.ca/~acoatley-willis/CheckLab5.py
python3 ./CheckLab5.py -f -v lab5b
</source>
:::4. Before proceeding, make certain that you identify any and all errors in lab5b.py. When the checking script tells you everything is OK before proceeding to the next step.
<br><br>




= INVESTIGATION 2: Exceptions and Error Handling =
Running into errors in programming will be a common occurrence. In python when a error occurs, python raises a python object called an exception, which represents the error that occured. These exceptions are raised when python is no long able to handle what the code is trying to do. This section will give the programmer the ability to catch these exceptions when they happen and allow the program to continue running, however in many cases it might be a good idea to stop the program when an exception happens anyway.

== PART 1 - Types of Errors ==
There are a massive amount of exceptions, way too many to cover. But if you are searching for a specific exception check out the [https://docs.python.org/3/library/exceptions.html#exception-hierarchy Python Exception Documentation.]
:'''Perform the Following Steps:'''
::#To start, open the ipython3 shell:<source lang="python">
ipython3
</source>
::#Before we try and catch and detect exceptions, lets make sure we know a few ways to make errors in python. The following code will create an error:<source lang="python">
print('5' + 10)
</source>
::#Immediately the following error occurs:<source lang="python">
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-3-1b929b80ca50> in <module>()
----> 1 print('5' + 10)

TypeError: Can't convert 'int' object to str implicitly
</source>
::#Firstly, what to look for here is the exception name '[https://docs.python.org/3/library/exceptions.html#TypeError TypeError.]' The Type error means a mismatch of a type(string, int, float, list, etc). Python doesn't know how to handle it, should it change the number into a string or change the string into a number?
::#If we want to write this program safely, we can catch this error while it's happening. This is done with a specific block of code called a [https://docs.python.org/3/tutorial/errors.html#handling-exceptions try clause] where you place code inbetween the '''try:''' and ''''except:'''. If no error occurs in the code the except portion will be skipped.
::#No Exception:<source lang="python">
try:
print(5 + 10)
except TypeError:
print('not an integer')

15
</source>
::#TypeError Exception:<source lang="python">
try:
print(5 + 'ten')
except TypeError:
print('not an integer')

not an integer
</source>
::#Try and open a file that doesn't exist:<source lang="python">
f = open('filethatdoesnotexist', 'r')
</source>
::#To catch this error specific error we could simply use:<source lang="python">
try:
f = open('filethatdoesnotexist', 'r')
f.write('hello world\n')
f.close()
except FileNotFoundError:
print('no file found')
</source>
::#Multiple exceptions can also be caught at the same time, such as does not exist, is a directory, or we don't have permission. Try removing permissions from the file, or creating a directory and opening it. <source lang="python">
try:
f = open('filethatdoesnotexist', 'r')
f.write('hello world\n')
f.close()
except (FileNotFoundError, PermissionError, IsADirectory):
print('failed to open file')
</source>
::#If you spend some time looking at the [https://docs.python.org/3/library/exceptions.html#exception-hierarchy Python Exception Hierarchy] we can see exactly how errors get caught in python. FileNotFoundError, PermissionError, and IsADirectory all inherit from OSError, this means that while using more specific errors might be useful for better error messages and handling, it's not always possible to catch every error all the time.::#Another way to catch multiple exceptions:<source lang="python">
try:
f = open(abc, 'r')
f.write('hello world\n')
f.close()
except (FileNotFoundError, PermissionError):
print('file does not exist or wrong permissions')
except IsADirectoryError:
print('file is a directory')
except OSError:
print('unable to open file')
except:
print('unknown error occured')
raise
</source>
::#When catching multiple exceptions, make sure to catch the lowest ones on the hierarchy first. If you put 'Exception' first, both 'OSError' and 'FileNotFoundError', would never get caught.
::#In python it's usually best to 'try:' and 'except:' code rather than to try and determine everything that could go wrong with logic and if statements. For example, instead of checking to see if a file exists and we have read permissions, it can be better to just try and read the file and fail and catch any errors with 'OSError'.

=== Create a Python Script Which Handles Errors ===
:'''Perform the Following Instructions'''
::#Create the '''~/ops435/lab5/lab5c.py''' script.
::#Use the following as a template:<source lang="python">
#!/usr/bin/env python3

def add(number1, number2):
# Add two numbers together, return the result, if error return string 'error: could not add numbers'

def read_file(filename):
# Read a file, return a list of all lines, if error return string 'error: could not read file'

if __name__ == '__main__':
print(add(10,5)) # works
print(add('10',5)) # works
print(add('abc',5)) # exception
print(read_file('file1.txt')) # works
print(read_file('file10000.txt')) # exception

</source>


::::'''Sample Run 1:'''<source lang="python">
python3 lab5c.py
15
15
error: could not add numbers
['Line 1\n', 'Line 2 is a little longer\n', 'Line 3 is too\n', 'This is the forth line\n', 'Final line in file\n']
error: could not read file
</source>

::::'''Sample Run 2 (with import):'''<source lang="python">
import lab5c

lab5c.add(10,5)
15

lab5c.add('10',5)
15

lab5c.add('10','5')
15

lab5c.add('abc','5')
'error: could not add numbers'

lab5c.add('hello','world')
'error: could not add numbers'

lab5c.read_file('file1.txt')
['Line 1\n',
'Line 2 is a little longer\n',
'Line 3 is too\n',
'This is the forth line\n',
'Final line in file\n']

lab5c.read_file('file10000.txt')
error: could not read file'


</source>


:::3. Exit the ipython3 shell, download the checking script and check your work. Enter the following commands from the bash shell.<source lang="bash">
cd ~/ops435/lab5/
pwd #confirm that you are in the right directory
ls CheckLab5.py || wget matrix.senecac.on.ca/~acoatley-willis/CheckLab5.py
python3 ./CheckLab5.py -f -v lab5c
</source>
:::4. Before proceeding, make certain that you identify any and all errors in lab5c.py. When the checking script tells you everything is OK before proceeding to the next step.
<br><br>





= LAB 5 SIGN-OFF (SHOW INSTRUCTOR) =
:'''Have Ready to Show Your Instructor:'''

::<span style="color:green;font-size:1.5em;">&#x2713;</span> x
::<span style="color:green;font-size:1.5em;">&#x2713;</span> x
::<span style="color:green;font-size:1.5em;">&#x2713;</span> Lab4 logbook notes completed
= Practice For Quizzes, Tests, Midterm & Final Exam =
# x
# x
# x
198
edits

Navigation menu