Post

File Handling in Python – Saving, Reading, Updating, and Deleting External Data

In real-world programming, data rarely lives entirely inside your code. This post explores Python’s built-in file handling capabilities, covering how to save, read, update, and delete external data using text and JSON files.

File Handling in Python – Saving, Reading, Updating, and Deleting External Data

Day 19 of Asabeneh Yetayeh’s 30 Days of Python introduces file handling. A built-in module in Python that helps developers work with external data.

While I would still consider myself a beginner, I’ve attempted applying this logic to a small program I made for generating passwords. This program allows users to store, update, and delete entries while generating new ones from memorable words that you provide.

The problems I encountered while learning to implement this process of reading and writing to a file were the functions. There are many options available with this, and I needed to get myself familiar with knowing how to use them.

Of course, I used a bit of AI to help me come up with the skeleton structure, but I went in and refined the code to make it my own. This is why I continue to revisit the topics until they stick with me.

In a real-world scenario, we’d probably think about the data type we’d use for the data and also what file type we need. For the purpose of being able to show that we can implement a basic function of reading and writing to a file, we’ll most likely stick to working with a normal text file (.txt).

By saving data externally—using formats such as .txt or .json—we separate program logic from program data. I need to be able to know how to create these functions in a manner that’s fit for the project I could be working with.

Opening Files and Their Modes

Python’s built-in open() function is the core module we need to get our function working. This takes two pieces of information; file path, and the mode we want the file opened in.

1
2
3
#syntax:

open('filename_and_location', 'mode')

File Modes Explained

The mode is what helps Python know what you would like to do with the file once it’s opened. You might have a program that you want to use to just read files like a PDF viewer, or you might want to append information to a file like a Microsoft Word document.

Selecting the correct mode is vital to Python, as the rest of the functions you wish to use will depend entirely on how the file is opened in or by Python. Here is a collated list of modes and what they do:

ModeNameDescription
rReadOpens a file for reading. Raises an error if the file does not exist. (Default)
aAppendOpens a file for appending. Creates the file if it does not exist.
wWriteOpens a file for writing and overwrites existing content. Creates the file if it does not exist.
xCreateCreates a new file. Raises an error if the file already exists.
tTextOpens the file in text mode. (Default)
bBinaryOpens the file in binary mode (used for images, audio, video, etc.).

Using the syntax I provided above, Using the syntax I provided above, I can go ahead and build my function to open a file.

Defining The File Path

I didn’t originally want to include this when writing this post, but as I revised over my own work, it became more apparent that it was a subtlety I needed to include.

In my previous post, I went over regular expressions and how to use them. I also went over string escape sequences and what they are.

Depending on how you specify the file path for what you want to work on, you may have to use these methods to allow Python to read them as a normal file path.

Here is a comparison:

1
2
# Method 1:
open(r'C:\Path\To\file.txt', 'r')
1
2
# Method 2:
open("/home/sheikh/Documents/file.txt", 'r')

Method 1 could be described as a traditional approach to providing file paths. The problem we’ll find with this method is that each backslash will be recognised as a character escape sequence, which we want to avoid. It’ll think \t' is tab space` and not part of the file path.

Method 2 is more appropriate, but I’ve taken this module through ChatGPT, and it’s informed me that the correct method is to use an imported function called pathlib with the attribute Path.

Using pathlib

This is an entirely new function that I have discovered while writing this post, and it’s important that I include as much as I can about it. The reason for this is that this is supposedly the professional method used in all Python projects.

1
from pathlib import Path

This enables your program to work with different Operating Systems like Mac, Linux, and Windows without causing any disruptions, making it scalable.

This is making me think about the rest of the modules now…

This module brings in many other functions, like Change Directory, list items in a directory, remove a file, and rename files.

As I haven’t been able to fully explore this function as of writing this, I’ll include some basic examples. Once I have taken the time to learn more on this module, I’ll go on ahead and create a post for it.

CommandWhat It DoesExampleOutput / Benefit
Path("file.txt")Create a Path objectfrom pathlib import Path
path = Path("log.txt")
Represents a file safely, works like a pointer to the file
Path.cwd()Get current working directoryPath.cwd()Shows where Python is looking for files; cross-platform
Path.home()Get user’s home folderPath.home()Works on all OS; avoids typing full paths like C:/Users/...
/ operatorJoin paths safelyPath("data") / "log.txt"Avoids slash mistakes; cross-platform
exists()Check if file/folder existspath.exists()Returns True / False; helps avoid errors
is_file()Check if path is a filepath.is_file()Returns True if it’s a file, not a folder
is_dir()Check if path is a directorypath.is_dir()Returns True if it’s a folder
read_text()Read whole file as textpath.read_text()Shortcut instead of open/read/close
write_text()Write text to filepath.write_text("Hello World")Creates file if it doesn’t exist, overwrites if it does
touch()Create an empty filePath("new.txt").touch()Quick way to make a new file
mkdir()Create a folderPath("data").mkdir()Creates folder; can use exist_ok=True to avoid errors
unlink()Delete a filePath("old.txt").unlink()Removes a file safely
rename()Rename or move a filePath("old.txt").rename("new.txt")Safe renaming/moving

Table built with ChatGPT

This is lazy work, I know. However, I really want to get down to using the built-in functions first and then work with imported functions later.

Reading a File

Now that we’ve gained some insight into the different methods used to open a file along with the modes available, let’s use some of them.

1
open("filename.txt", 'r')

This has opened the file in read mode. We can now tell Python to read the contents and output them into our terminal.

1
2
3
4
file = open("filename.txt", 'r')
data = file.read()
print(data)
file.close() # Always look to close the file once done

We have now told Python to open the file as read and placed that in file, we’ve then poured the contents into data by using .read(), and finally, we’ve instructed Python to place the contents into the terminal.

Output:

I will not encourage others to fly. I will not encourage others to fly…

Bart Simpson — if you know, you know.

Why Closing a File Matters

If I’m honest, I’ve not really used this much throughout projects that I have made. A recommendation made by none other than ChatGPT says that we should use this where possible.

I can understand when it comes to larger systems and for scalability, rather, I keep this knowledge as useful to know when it’s required to use.

Leaving them open unnecessarily can lead to:

  • Memory leaks
  • Locked files
  • Unexpected program behaviour

Open file → Work with file → Save changes → Close file

This again places more emphasis on thinking and being like developers to ensure the proper logical flow of a system than anything else.

Common File Methods

Hitherto, we’ve explored opening files and closing them using the correct mode. I need to learn how to process files and make changes to them as I want.

Python has many methods that we can use to read, write, and update or amend a file.

CategoryMethodWhat It DoesExampleResult
Readingread()Reads the entire file as a single stringf.read()'Hello\nWorld'
 read(n)Reads first n charactersf.read(5)'Hello'
 readline()Reads one linef.readline()'Hello\n'
 readlines()Reads all lines into a listf.readlines()['Hello\n', 'World\n']
 splitlines()Removes newline charactersf.read().splitlines()['Hello', 'World']
Writingwrite()Writes a string to a filef.write('Hello')File updated
 writelines()Writes a list of stringsf.writelines(lines)Writes as-is
Controlseek()Moves cursor positionf.seek(0)Reset pointer
 tell()Returns cursor positionf.tell()5
 truncate()Cuts file at cursorf.truncate()File shortened
Safetyclose()Closes filef.close()File released
 with open()Auto-closes filewith open() as f:Safer handling

Note: Opening a file does nothing on its own. Methods such as .read() or .write() are required to interact with its contents.

Using with open() (Best Practice)

Earlier, I mentioned that it’s important to close a file that you are working with once your program has completed its actions.

Python provides a with function that only keeps the file open while you perform some functions and then closes it automatically.

It also refactors code by placing the open file into a variable on load using as, removing the need for creating a variable and then placing the open file there.

1
2
3
with open('filename.txt', 'r') as f:
    txt = f.read()
    print(txt)

Output:

I will not encourage others to fly. I will not encourage others to fly. I will not encourage others to fly…

Reading and Writing Together

I’ll now show you how to append information to a file. There are different approaches you can take with this; one method will overwrite the complete file, another will append the changes to the end of the file.

For this demonstration, we’ll use a to append to the file at the end, as this is usually what we would do.

1
2
3
4
5
6
7
8
9
def write_to_file(filename_and_path, new_text):
    with open(filename_and_path, 'a') as file:
        file.write(new_text)

    with open(filename_and_path, 'r') as file:
        data = file.read()
        print(data)

write_to_file('filename.txt', 'Hello, this is appending text.')

Output:

I will not encourage others to fly. I will not encourage others to fly…Hello, this is appending text.

If we opened the file as w or write and then appended some information, it would rewrite over the file and the output would be different.

1
2
3
4
5
6
7
8
9
def write_to_file(filename_and_path, new_text):
    with open(filename_and_path, 'w') as file:
        file.write(new_text)

    with open(filename_and_path, 'r') as file:
        data = file.read()
        print(data)

write_to_file('filename.txt', 'Hello, this is appending text.')

Output:

Hello, this is appending text.

Daily Summary

Quite frankly, this topic was easier to digest than some of the more advanced topics that I’ve covered. It makes me feel as though I am ready to start coding in Python for larger projects but I do feel like I’ve got a “code block”. A lot of the functions and modules discussed in this chapter are all easier to remember as they work like a mnemonic making coding really good with it too.

I get that most of the information discussed were all around using a .txt file which is a little unfair; however, using .json files are more toward specific applications that’ll use lists or dictionaries as storage. I believe that the reason why I have a roadblock in coding is because I am not actively creating projects.

I will sit and just research countlessly, watch videos, do some tutorials. While this is really good, it prevents me from applying any of my newly found knowledge to help retain the information and gain a deeper insight.

This post is licensed under CC BY 4.0 by the author.