Everything your programs have worked with so far has lived in memory — variables, lists, dicts — and vanished the moment the program ended. Files let a program persist data, read data other programs (or humans) produced, and exchange data with the outside world.
f = open("notes.txt")
content = f.read()
f.close()
This works, but it has a real problem: if something goes wrong between open and close (an exception, a return you forgot moves past the close, anything), the file is left open — a resource leak. On a short-lived script that rarely matters, but it's a bad habit to build.
with statementPython's fix is the with statement — it guarantees the file gets closed automatically, no matter how the block exits (normally, via return, or via an exception):
with open("notes.txt") as f:
content = f.read()
# f is automatically closed here, even if read() raised
This is the idiomatic way to work with files in Python, and the only style you'll use in this section. open(path) as f gives you a file object f inside the block; once the block ends (for any reason), the file is closed for you.
open() takes a second argument controlling how the file is opened:
open(path) # "r" (read) is the default -- fails if the file doesn't exist
open(path, "r") # read -- same as above, explicit
open(path, "w") # write -- creates the file if it doesn't exist, ERASES existing content
open(path, "a") # append -- creates the file if it doesn't exist, adds to the end otherwise
The difference between "w" and "a" matters a lot: opening a file in "w" mode truncates it — whatever was there before is gone the moment you open it, even if you never write anything. If you want to add to a file without destroying what's already in it, you need "a".