Read, write, and create files in Python (with and open())

Modified: | Tags: Python, File

In Python, the open() function allows you to read a file as a string or list, and create, overwrite, or append a file.

Read and write files with open() and with

For both reading and writing scenarios, use the built-in open() function to open the file.

The file object, indicated by the path string specified in the first argument, is opened. Use the mode argument to specify read or write, text or binary. Details are described below.

Paths can be either absolute or relative to the current directory. You can check the current directory with os.getcwd() and change it with os.chdir().

Text files are read as io.TextIOWrapper object.

path = 'data/src/test.txt'

f = open(path)

print(type(f))
# <class '_io.TextIOWrapper'>

f.close()

As shown in the example above, you need to close the file object using the close() method. Alternatively, a with block automatically closes the file when the block ends, providing a more convenient approach.

with open(path) as f:
    print(type(f))
# <class '_io.TextIOWrapper'>

You can use any variable name for the xxx in with open() as xxx:. It represents a file object opened with open(), named xxx, and used within the block. While f is commonly used, other names are also acceptable.

Encoding specification: encoding

Specify the encoding for reading or writing text files with the encoding argument of open(). The encoding string can be in uppercase or lowercase and can use either a hyphen - or an underscore _. For example, both 'UTF-8' and 'utf_8' are allowed.

Refer to the official documentation for the encodings supported by Python.

The default value of encoding depends on the platform. You can check it with locale.getpreferredencoding().

import locale

print(locale.getpreferredencoding())
# UTF-8

Read text files

Open a file for reading: mode='r'

To open a file for reading, set the mode argument of open() to 'r'. The default value for the mode argument is 'r', so you can omit it. In the following examples, it is omitted.

If you specify a non-existent path in mode='r', you will get an error (FileNotFoundError).

# with open('data/src/test_error.txt') as f:
#     print(type(f))
# FileNotFoundError: [Errno 2] No such file or directory: 'data/src/test_error.txt'

Read the entire file as a string: read()

To read the entire file into a single string, use the read() method on the file object.

with open(path) as f:
    s = f.read()
    print(type(s))
    print(s)
# <class 'str'>
# line 1
# line 2
# line 3

Although the file object is closed at the end of the with block, the assigned variable remains accessible outside the block.

with open(path) as f:
    s = f.read()

print(s)
# line 1
# line 2
# line 3

Read the entire file as a list: readlines()

To read the entire file as a list of lines, use the readlines() method. All lines except the last one include a newline character \n at the end.

with open(path) as f:
    l = f.readlines()
    print(type(l))
    print(l)
# <class 'list'>
# ['line 1\n', 'line 2\n', 'line 3']

If you want to remove the trailing newline character, you can use a list comprehension and call rstrip() on each element.

with open(path) as f:
    l_strip = [s.rstrip() for s in f.readlines()]
    print(l_strip)
# ['line 1', 'line 2', 'line 3']

Read a file line by line: readline()

When iterating over the file object with a for loop, you can retrieve each line as a string (including the newline character at the end). Here, repr() is used to display the newline character as is.

with open(path) as f:
    for s_line in f:
        print(repr(s_line))
# 'line 1\n'
# 'line 2\n'
# 'line 3'

To read one line at a time, use next(). An error occurs if there are no more lines to read.

with open(path) as f:
    print(repr(next(f)))
    print(repr(next(f)))
    print(repr(next(f)))
#     print(repr(next(f)))
#     StopIteration:
# 'line 1\n'
# 'line 2\n'
# 'line 3'

The readline() method of the file object can also retrieve one line at a time, but it does not raise an error after EOF (end of file) and continues to return an empty string ''.

with open(path) as f:
    print(repr(f.readline()))
    print(repr(f.readline()))
    print(repr(f.readline()))
    print(repr(f.readline()))
    print(repr(f.readline()))
# 'line 1\n'
# 'line 2\n'
# 'line 3'
# ''
# ''

Write text files

Open a file for writing: mode='w'

To open a file for writing, set the mode argument of open() to 'w'. The file's contents will be overwritten if it exists, or a new file will be created if it does not.

Be careful not to specify a non-existent directory for the new file, as this will result in an error (FileNotFoundError).

# with open('data/src/new_dir/test_w.txt', mode='w') as f:
#     f.write(s)
# FileNotFoundError: [Errno 2] No such file or directory: 'data/src/new_dir/test_w.txt'

Write a string: write()

To write a string to a file, use the write() method on the file object.

path_w = 'data/temp/test_w.txt'

s = 'New file'

with open(path_w, mode='w') as f:
    f.write(s)

with open(path_w) as f:
    print(f.read())
# New file

Strings containing newline characters are written without any modification.

s = 'New line 1\nNew line 2\nNew line 3'

with open(path_w, mode='w') as f:
    f.write(s)

with open(path_w) as f:
    print(f.read())
# New line 1
# New line 2
# New line 3

For more information on strings with line breaks, see the following article:

The write() method only accepts strings as arguments. Passing a different type, such as an integer (int) or a floating-point number (float), will result in a TypeError. To write a non-string value, convert it to a string using str() before passing it to write().

Write a list: writelines()

To write a list of strings to a file, use the writelines() method. Note that this method does not automatically insert line breaks.

l = ['One', 'Two', 'Three']

with open(path_w, mode='w') as f:
    f.writelines(l)

with open(path_w) as f:
    print(f.read())
# OneTwoThree

To write each element of the list on a separate line, create a string containing newline characters by using the join() method.

with open(path_w, mode='w') as f:
    f.write('\n'.join(l))

with open(path_w) as f:
    print(f.read())
# One
# Two
# Three

The writelines() method only accepts lists containing strings as elements. If you want to write a list with elements of other types, such as integers (int) or floating-point numbers (float), you need to convert the list to a list of strings. See the following article:

Create an empty file: pass

To create an empty file, open a new file in write mode (mode='w') without writing any content.

Since the with block requires some statement to be written, use the pass statement, which does nothing.

with open('temp/empty.txt', 'w'):
    pass

Create a file only if it doesn't exist

Using mode='w' can accidentally overwrite an existing file.

To write to a file only if it doesn't exist, i.e., create a new file without overwriting, you can use one of the following two methods:

Open a file for exclusive creation: mode='x'

To create a new file only if it does not already exist, set the mode argument of open() to 'x'. If the specified file exists, a FileExistsError will be raised.

# with open(path_w, mode='x') as f:
#     f.write(s)
# FileExistsError: [Errno 17] File exists: 'data/src/test_w.txt'

By using try and except for exception handling, you can create a new file if it doesn't exist and take no action if it already exists.

try:
    with open(path_w, mode='x') as f:
        f.write(s)
except FileExistsError:
    pass

Check if the file exists before opening

Use the os.path.isfile() function from the os.path module in the standard library to check if a file exists.

import os

if not os.path.isfile(path_w):
    with open(path_w, mode='w') as f:
        f.write(s)

Append to a file

Open a file for appending: mode='a'

To open a file for appending, set the mode argument of open() to 'a'.

write() and writelines() will append to the end of an existing file.

with open(path_w, mode='a') as f:
    f.write('Four')

with open(path_w) as f:
    print(f.read())
# One
# Two
# ThreeFour

If you want to add a final line, include the newline character when appending.

with open(path_w, mode='a') as f:
    f.write('\nFour')

with open(path_w) as f:
    print(f.read())
# One
# Two
# ThreeFour
# Four

Note that if the file does not exist, it will be created as a new file, just like when mode='w' is used.

Insert at the beginning or in the middle

mode='r+'

When the mode argument of open() is set to 'r+', the file is opened in update mode.

write() and writelines() will overwrite the existing file from the beginning.

with open(path_w, mode='r+') as f:
    f.write('12345')

with open(path_w) as f:
    print(f.read())
# 12345wo
# ThreeFour
# Four

In the example above, One\nTwo is overwritten by 12345 from the beginning, resulting in 12345wo. The \n is treated as one character.

You can also move the position by using the seek() method of the file object, but you need to specify the position in characters, not lines. This will also overwrite.

with open(path_w, mode='r+') as f:
    f.seek(3)
    f.write('---')

with open(path_w) as f:
    print(f.read())
# 123---o
# ThreeFour
# Four

readlines() and insert()

If the text file is not huge, it is easier to read the entire file as a list using readlines() and process it. The insert() method of the list allows you to insert new strings at the beginning or in the middle of the lines.

Read the file as a list with readlines(), insert an element using insert(), and then write the updated list using writelines().

You can specify the number of lines to insert in the first argument of insert().

with open(path_w) as f:
    l = f.readlines()

l.insert(0, 'FIRST\n')

with open(path_w, mode='w') as f:
    f.writelines(l)

with open(path_w) as f:
    print(f.read())
# FIRST
# 123---o
# ThreeFour
# Four

For adding, inserting, and removing elements to a list, see the following articles:

Read and write binary files

Adding a b to the end of the mode argument enables reading and writing binary files. For example, mode='rb' is for reading binary files, and mode='ab' is for appending to the end of binary files.

Like text files, binary files also support read(), readline(), readlines(), write(), and writelines() as methods of the file object.

To open, process, and save image files, use libraries such as Pillow or OpenCV.

Related Categories

Related Articles