These are simple thing that many computer users already know, but I'll go through them just to make sure you know them also.
- Each file has a name, like
hello.py,mytext.txtorcoolimage.png. Usually the name ends with an extension that describes the content, likepyfor Python,txtfor text orpngfor "portable network graphic". - With just names identifying the files, it wouldn't be possible to have two files with the same name. That's why files also have a location. We'll talk more about this in a moment.
- Files have content that consists of 8-bit bytes.
Directories are a way to group files. They also have a name and a location like files, but instead of containing data directly like files do they contain other files and directories.
Directories and files have a path, like C:\Users\me\hello.py. That just
means that there's a folder called C:, and inside it there's a folder
called Users, and inside it there's a folder called me and inside it
there's a hello.py. Like this:
C:
└── Users
└── me
└── hello.py
C:\Users\me\hello.py is an absolute path. But there are also
relative paths. For example, if you're in C:\Users, me\hello.py
is same as C:\Users\me\hello.py. The place we are in is sometimes
called current directory, working directory or
current working directory.
So far we've talked about Windows paths, but not all computers run
Windows. For example, an equivalent to C:\Users\me\hello.py is
/home/me/hello.py on my Ubuntu, and if I'm in /home, me/hello.py
is same as /home/me/hello.py.
/
└── home
└── me
└── hello.py
Let's create a file and write a hello world to it.
>>> with open('hello.txt', 'w') as f:
... print("Hello World!", file=f)
...
>>> Doesn't seem like it did anything. But actually it created a hello.txt
somewhere on your system. On Windows it's probably in C:\Users\YourName,
and on most other systems it should be in /home/yourname. You can open
it with notepad or any other plain text editor your system comes with.
So how does that code work?
First of all, we open a path with open, and it gives us a Python file
object that is assigned to the variable f.
>>> f
<_io.TextIOWrapper name='hello.txt' mode='w' encoding='UTF-8'>
>>> So the first argument we passed to open was the path we wanted to write.
Our path was more like a filename than a path, so the file ended up in
the current working directory.
The second argument was w... but where the heck does that come from?
w is short for write, and that just means that we'll create a new file.
There's some other modes you can use also:
| Mode | Short for | Meaning |
|---|---|---|
r |
read | Read from an existing file. |
w |
write | Write to a file. If the file exists, its old content is removed. |
a |
append | Write to the end of a file, and keep the old content. |
The w and a modes create a new file if it exists already, but trying
to read from a non-existent file is an error.
But what is that with ourfile as f crap? That's just a fancy way to make
sure that the file gets closed, no matter what happens. As you can see,
the file was indeed closed.
>>> f.closed
True
>>> When we had opened the file we could just print to it. The print is just
like any other print, but we also need to specify that we want to print
to the file we opened using file=f.
After opening a file with the r mode you can for loop over it, just
like it was a list. So let's go ahead and read everything in the file
we created to a list of lines.
>>> lines = []
>>> with open('hello.txt', 'r') as f:
... for line in f:
... lines.append(line)
...
>>> lines
['Hello World!\n']
>>> But why is there a \n at the end of our hello world?
\n means newline. Note that it needs to be a backslash, so /n
doesn't have any special meaning like \n has. When we wrote the file
with print it actually added a \n to the end of it. It's good practise
to end the content of files with a newline character, but it's not
necessary.
So how does that work if we have more than one line in the file?
>>> with open('hello.txt', 'w') as f:
... print("Hello one!", file=f)
... print("Hello two!", file=f)
... print("Hello three!", file=f)
...
>>> lines = []
>>> with open('hello.txt', 'r') as f:
... for line in f:
... lines.append(line)
...
>>> lines
['Hello one!\n', 'Hello two!\n', 'Hello three!\n']
>>> There we go, each of our lines now ends with a \n. When we for
loop over the file it's divided into lines based on where the \n
characters are, not based on how we printed to it.
But how to get rid of that \n? The rstrip
string method is great
for this:
>>> stripped = []
>>> for line in lines:
... stripped.append(line.rstrip('\n'))
...
>>> stripped
['Hello one!', 'Hello two!', 'Hello three!']
>>> It's also possible to read lines one by one. Files have a
readline() method that reads the next line, and returns ''
if we're at the end of the file.
TODO: example of readline()
There's only one confusing thing about reading files. If you try to read it twice you'll find out that it only gets read once:
>>> first = []
>>> second = []
>>> with open('hello.txt', 'r') as f:
... for line in f:
... first.append(line)
... for line in f:
... second.append(line)
...
>>> first
['Hello one!\n', 'Hello two!\n', 'Hello three!\n']
>>> second
[]
>>> But if we open the file again, everything works.
>>> first = []
>>> second = []
>>> with open('hello.txt', 'r') as f:
... for line in f:
... first.append(line)
...
>>> with open('hello.txt', 'r') as f:
... for line in f:
... second.append(line)
...
>>> first
['Hello one!\n', 'Hello two!\n', 'Hello three!\n']
>>> second
['Hello one!\n', 'Hello two!\n', 'Hello three!\n']
>>> Usually it's best to just read the file once, and use the content you have read from it multiple times.
As you can see, files behave a lot like lists. The join()
string method joins together strings from a list, but we can
also use it to join together lines of a file:
>>> with open('hello.txt', 'r') as f:
... full_content = ''.join(f)
...
>>> full_content
'Hello one!\nHello two!\nHello three!\n'
>>> But if you need all of the content as a string, you can just
use the read() method.
>>> with open('hello.txt', 'r') as f:
... full_content = f.read()
...
>>> full_content
'Hello one!\nHello two!\nHello three!\n'
>>> TODO: Explain paths and \.
The following program prints the contents of files:
while True:
filename = input("Filename or path, or nothing at all to exit: ")
if filename == '':
break
with open(filename, 'r') as f:
# We could read the whole file at once, but this is
# faster if the file is very large.
for line in f:
print(line.rstrip('\n'))This program stores the user's username and password in a file. Plain text files are definitely not a good way to store usernames and passwords, but this is just an example.
# Ask repeatedly until the user answers 'y' or 'n'.
while True:
answer = input("Have you been here before? (y/n) ")
if answer == 'Y' or answer == 'y':
been_here_before = True
break
elif answer == 'N' or answer == 'n':
been_here_before = False
break
else:
print("Enter 'y' or 'n'.")
if been_here_before:
# Read username and password from a file.
with open('userinfo.txt', 'r') as f:
username = f.readline().rstrip('\n')
password = f.readline().rstrip('\n')
if input("Username: ") != username:
print("Wrong username!")
elif input("Password: ") != password:
print("Wrong password!")
else:
print("Correct password, welcome!")
else:
# Write username and password to a file.
username = input("Username: ")
password = input("Password: ")
with open('userinfo.txt', 'w') as f:
print(username, file=f)
print(password, file=f)
print("Done! Now run this program again and select 'y'.")You may use this tutorial freely at your own risk. See LICENSE.