lec-19
Marc Schroeder is present in class today and is conducting observations as part of an approved research study. No audio or video recording is being conducted.
His fieldnotes may record general observations about the overall nature of classroom activities and discussions. However, these will not include personal or identifying details about individuals or their participation, except for those students who are participating in other aspects of the study.
If you have any questions or concerns, then please let me know, and I’ll direct you to the appropriate resource.
Get the updated files into your Codespace.
Diff tools are your friend.
⦾ reading from text files
⦾ writing to text files
Sometimes stuff is in a text file and you want it badly. Yes you do.
Sometimes you want to put stuff in a text file. For posterity, or something.
The details of working with text files in various languages can vary quite a bit.
But while the details of working with files in Python will differ from Java, C++, JS, PHP, etc...the general steps are going to be reassuringly similar.
A very simple thing we can do with smaller text files is just read the whole darn thing into a string, then do whatever we want with that string.
TASK 1
Write a program that reads in somebody's A3 assignment file and then writes out a "sushified" version of that assignment - to another file - with all o's replaced with 🍥.
MAY I HAVE A VOLUNTEER FROM THE AUDIENCE?
Narutomaki - a type of kameboko
emoji from emojiterra
Write a program that reads in somebody's A3 assignment file and then writes out a "sushified" version of that assignment with all o's replaced with 🍥.
Let's dig in.
file_reader = open("assign3.py", "r")
TASK 1
Write a program that reads in somebody's A3 assignment file and then writes out a "sushified" version of that assignment with all o's replaced with 🍥.
open is a function you can just use in Python - no import needed
the first argument to open is a string - the path to the file you want to open
the second arg to open is the mode - here, we want to open for (r)eading
open returns a useful minion - he's "smart", like strings and lists are, so we can "talk" to him with various methods
JP: remember to demo relative file paths by putting the data file in a folder, triple-nested folder (because they have to figure out the double by themselves)
file_reader = open("assign3.py", "r")
assignment_text = file_reader.read()TASK 1
Write a program that reads in somebody's A3 assignment file and then writes out a "sushified" version of that assignment with all o's replaced with 🍥.
we start talking to our file_reader minion, by calling a method...
...the read method. It returns EVERYTHING in the text file as one big string...
...which we store in a hopefully well-named variable.
JP: barf out the text to console so they don't think you're a lyin' varmit.
🙋🏻♂️❓🙋🏻♀️What character is used to represent a new line in a string? How could we check?
file_reader = open("assign3.py", "r")
assignment_text = file_reader.read()
sushified_text = assignment_text.replace("o", "🍥")TASK 1
Write a program that reads in somebody's A3 assignment file and then writes out a "sushified" version of that assignment with all o's replaced with 🍥.
we want the string to replace all o's with 🍥, so we "talk" to the string using...
...the replace method. It returns a NEW string, with all X replaced by Y...
...which we store in a well-named variable.
JP: barf out the replaced text. Oh, and go over that replace/immutable thing, too.
X
Y
🙋🏻♂️❓🙋🏻♀️What was our goal again here? What can we do with our string to make our goal happen?
file_reader = open("assign3.py", "r")
assignment_text = file_reader.read()
sushified_text = assignment_text.replace("o", "🍥")
file_reader.close()TASK 1
Write a program that reads in somebody's A3 assignment file and then writes out a "sushified" version of that assignment with all o's replaced with 🍥.
since we're done using the file, we tell our minion to release its grip on the file...
...by calling the close method. Forgetting to do this may be bad news.
JP: try renaming the file before closing. - this might work in a Codespace, but will cause you grief in Windows!
...
You're reading this too late, aren't you.
file_reader = open("assign3.py", "r")
assignment_text = file_reader.read()
sushified_text = assignment_text.replace("o", "🍥")
file_reader.close()TASK 1
Write a program that reads in somebody's A3 assignment file and then writes out a "sushified" version of that assignment with all o's replaced with 🍥.
JP: any questions?
Write a program that reads in somebody's A3 assignment file and then writes out a "sushified" version of that assignment with all o's replaced with 🍥.
file_writer = open("assign3_sushified.py", "w")TASK 1
Write a program that reads in somebody's A3 assignment file and then writes out a "sushified" version of that assignment with all o's replaced with 🍥.
here's the function open again, called with different arguments this time
the first argument is - again - the path to the file you want to open
the second arg to open is the mode - here, we want to open for (w)riting
here we have another minion - he's the same type of thing as before, but since we've created him with "w", we can "talk" to him using some different methods
JP: open up the file
🙋🏻♂️❓🙋🏻♀️Where will the file be saved? How can we save it in a subfolder?
file_writer = open("assign3-sushified.py",
"w",
encoding="utf-8")
file_writer.write(sushified_text)TASK 1
Write a program that reads in somebody's A3 assignment file and then writes out a "sushified" version of that assignment with all o's replaced with 🍥.
we ask our minion to write our string to the file...
...using the write method...
JP: feign surprise at the file contents
...passing the string to be written to the file as an argument
file_writer = open("assign3-sushified.py",
"w",
encoding="utf-8")
file_writer.write(sushified_text)
file_writer.close()TASK 1
Write a program that reads in somebody's A3 assignment file and then writes out a "sushified" version of that assignment with all o's replaced with 🍥.
we ask our minion to close its connection to the file...
...using the close method...
TASK 1
Write a program that reads in somebody's A3 assignment file and then writes out a "sushified" version of that assignment with all o's replaced with 🍥.
file_reader = open("assign3.py", "r")
assignment_text = file_reader.read()
sushified_text = assignment_text.replace("o", "🍥")
file_reader.close()
file_writer = open("assign3-sushified.py", "w")
file_writer.write(sushified_text)
file_writer.close()It's nice to keep things separated into functions, each one doing one job.
def file_contents(file_path: str) -> str:
file_reader = open(file_path, "r")
text = file_reader.read()
file_reader.close()
return text
def write_contents(file_path: str, contents: str) -> None:
file_writer = open(file_path, "w")
file_writer.write(contents)
file_writer.close()
def sushified(text: str) -> str:
return text.replace("o", "🍥")
def main() -> None:
assignment_text = file_contents("assign3.py")
sushified_text = sushified(assignment_text)
write_contents("assign3-sushified.py", sushified_text)
main()
...and that our main tells a clear, simple story.
Notice that our functions are short, expressive, and easy to understand...
If the file contains records you want to process, we usually want to process that file line by line - record by record.
Three common scenarios:
Let's try the first thing.
TASK 2
Find the number of traffic incidents in Calgary in 2023 that involved a cyclist.
data.calgary.ca has many cool datasets like these traffic-related ones
As a side note, Google's dataset search tool is another good place to find lots of interesting data to play around with.
Westbound 16 Avenue at Deerfoot Trail NE ,Stalled vehicle. Partially blocking the right lane,6/21/2022 7:31,NE,-114.0266867,51.06748513
11 Avenue and 4 Street SW ,Traffic incident. Blocking multiple lanes,6/21/2022 4:02,SW,-114.0714806,51.04262449
68 Street and Memorial Drive E ,Traffic incident.,6/20/2022 23:53,NE,-113.9355533,51.05247351
...CAREFUL! This is a TEXT FILE, so any "numbers" in here are actually strings!
incidents.csvlocation info
description
start date/time
city quadrant
longitude
latitude
🙋🏻♂️❓🙋🏻♀️Looking at the data, what do you suppose the delimiter is?
🙋🏻♂️❓🙋🏻♀️How do we know whether a cyclist was involved in an incident?
fields
file_reader = open("incidents.csv", "r")file_reader = open("incidents.csv", "r")
for line in file_reader:
#do something useful with lineInside the loop, line will refer to one LINE from the file.
Westbound 16 Avenue at Deerfoot Trail NE ,Stalled vehicle. Partially blocking the right lane,6/21/2022 7:31,NE,-114.0266867,51.06748513
11 Avenue and 4 Street SW ,Traffic incident. Blocking multiple lanes,6/21/2022 4:02,SW,-114.0714806,51.04262449
68 Street and Memorial Drive E ,Traffic incident.,6/20/2022 23:53,NE,-113.9355533,51.05247351🙋🏻♂️❓🙋🏻♀️What would the result of that be? Could there be any issues with that?
In this file, the first time through the loop, line will be what?
The second time through, it will be what?
🙋🏻♂️❓🙋🏻♀️Is "line" a good name?
Can you suggest an alternative?
file_reader = open("incidents.csv", "r")
num_cyclist_incidents = 0
for line in file_reader:
# 1) see if line involves a cyclist and...
# 2) ...bump up our variable if it doesYou totally know how to do 1) and 2) mentioned in the comments above!
So get coding.
🙋🏻♂️❓🙋🏻♀️What's this pattern called?
🙋🏻♂️❓🙋🏻♀️What was our goal again? (Keep your eyes on the prize.)
Turn the code from the previous slide into a well-named function.
What parameters should it have?
Return type?
TASK 3
Create a list of all the incidents in the file that took place in the SW. Assume we're only interested in the latitude and longitude of those incidents, so our list should just have those things.
file_reader = open("some-file.txt", "r")
result = ???
for line in file_reader:
# 1) if the record is of interest...
# 2) ...put it in the list we're buildingYou totally know how to do 1) and 2) mentioned in the comments above!
So get coding.
🙋🏻♂️❓🙋🏻♀️What's this pattern called?