Change language

The basics of working with files in Python

| | | | | |

Interacting with the file system allows you to store information from the program. We will explain the basic functionality of the Python programming language for working with files.

Python's built-in features

The base for working with files - the built-in open() function

open(file, mode="rt")

This function has two arguments. The file argument takes a string that contains the path to the file. The second argument, mode, allows you to specify the mode in which you want to work with the file. By default, this argument takes the value "rt".

These modes can be combined. For example, "rb" opens a binary file for reading. By combining "r+" or "w+" you can open the file in both read and write mode simultaneously, with one difference: the first mode will raise an exception if the file does not exist and working in the second mode will create it.

You can begin to work with the file itself using an object of class io.TextIOWrapper, which is returned by the open() function. This object has several attributes, through which you can get information

  • name - file name;
  • mode - mode in which this file is open;
  • closed - returns True, if the file is closed.

When you are done with the file, you need to close it using the close() method

f = open("examp.le", "w")
//  working with file
f.close()

However, a more pythonic way of working with a file using built-in tools is to use the construct with . as …, which works as a context manager. The example above can be rewritten using it

with open("examp.le", "w") as f:
// working with file

The main difference is that python closes the file on its own, and the developer doesn't need to remember this. And a bonus to this is that exceptions will not be raised when opening the file (for example, if the file does not exist).

Reading from a file

When opening a file in modes that allow reading, several approaches can be used.

To begin with, you can read the file as a whole and write all the data in it to a single line.

with open("examp.le", "r") as f:
    text = f.read()

Using this function with an integer argument, you can read a certain number of characters.

with open("examp.le", "r") as f:
    part = f.read(16)

Only the first 16 characters of the text will be retrieved. It is important to understand that when you apply this function several times in a row, part after part of this text will be read - the virtual cursor will be shifted by the read text part. It can be moved by a certain position, if necessary, using the seek() method.

with open("examp.le", "r") as f: # 'Hello, world!'
    first_part = f.read(8)       # 'Hello, w'
    f.seek(4)
    second_part = f.read(8)      # 'o, world'

Another way is to read the file line by line. The readline() method reads a line and, as with the read() method, shifts the cursor, only this time by the whole line. Applying this method several times will result in reading several lines. Similar to this method, another method allows you to read a file as a whole, but line by line, writing them to a list. This list can be used, for example, as an iterated object in a loop.

with open("examp.le", "r") as f:
    for line in f.readlines():
        print(line)

But here, too, there is a more pythonic way. It consists in the fact that the io.TextIOWrapper object itself has an iterator that returns line by line. This way you don't need to read the whole file, saving it to a list, but you can dynamically read the file line by line. And do it in a concise way.

with open("examp.le", "r") as f:
    for line in f:
        print(line)

Writing into the file

The functionality of writing data to a file does not depend on whether it is adding data or overwriting the file. There are several approaches in performing this operation as well.

The simplest and most logical is to use the write() function

with open("examp.le", "w") as f:
    f.write(some_string_data)

The important thing is that only strings can be passed as arguments to the function. If you need to write other kinds of information, you have to explicitly convert it to a string type, using str(self) methods for objects or formatted strings.

It is possible to write a large amount of data to a file if it can be represented as a list of strings.

with open("examp.le", "w") as f:
    f.writelines(list_of_strings)

There is another nuance here, related to the fact that write() and writelines() do not automatically put a line break character, and this must be controlled by the developer himself.

There is another, less known, but perhaps the most convenient way. And, strange as it may seem, it is to use the print() function. At first, this statement may seem strange, because it is well known that it is used to print to the console. And it is true. But if we pass in an optional argument to file an object of type io.TextIOWrapper, which is the file object we are working with, then the output stream of print() is redirected from the console to the file.

with open("examp.le", "w") as f:
    print(some_data, file=f)

The strength of this approach is that we can pass not necessarily string arguments to print() - if necessary, the function will convert them to a string type itself.

At this point we can conclude our introduction to basic functionality of working with files. At the same time it is worth to say that Python is not the only language Python can use. There are many libraries which allow to work with files of certain types and work more closely with the file system. Together they give developers an easy and comfortable way to work with files.