Spotter Now This tutorial has a related video form created by the Existent Python team. Lookout it together with the written tutorial to deepen your understanding: Reading and Writing Files in Python

I of the most common tasks that yous tin can do with Python is reading and writing files. Whether it's writing to a elementary text file, reading a complicated server log, or even analyzing raw byte information, all of these situations require reading or writing a file.

In this tutorial, y'all'll learn:

  • What makes up a file and why that'south important in Python
  • The basics of reading and writing files in Python
  • Some basic scenarios of reading and writing files

This tutorial is mainly for beginner to intermediate Pythonistas, but at that place are some tips in here that more advanced programmers may appreciate as well.

What Is a File?

Before we can become into how to work with files in Python, information technology's important to understand what exactly a file is and how modernistic operating systems handle some of their aspects.

At its cadre, a file is a contiguous prepare of bytes used to store data. This data is organized in a specific format and can exist annihilation as unproblematic as a text file or as complicated as a program executable. In the cease, these byte files are so translated into binary i and 0 for easier processing by the computer.

Files on well-nigh modernistic file systems are composed of three master parts:

  1. Header: metadata about the contents of the file (file name, size, type, and so on)
  2. Data: contents of the file every bit written by the creator or editor
  3. Finish of file (EOF): special character that indicates the stop of the file
The file format with the header on top, data contents in the middle and the footer on the bottom.

What this information represents depends on the format specification used, which is typically represented by an extension. For case, a file that has an extension of .gif most likely conforms to the Graphics Interchange Format specification. There are hundreds, if not thousands, of file extensions out there. For this tutorial, you'll only bargain with .txt or .csv file extensions.

File Paths

When you access a file on an operating organization, a file path is required. The file path is a string that represents the location of a file. It'due south broken upward into three major parts:

  1. Folder Path: the file folder location on the file system where subsequent folders are separated by a forrard slash / (Unix) or backslash \ (Windows)
  2. File Name: the bodily proper noun of the file
  3. Extension: the end of the file path pre-pended with a period (.) used to bespeak the file type

Here's a quick example. Let's say you have a file located within a file construction like this:

                                / │ ├── path/ |   │ │   ├── to/ │   │   └── cats.gif │   │ │   └── dog_breeds.txt | └── animals.csv                              

Allow's say you lot wanted to access the cats.gif file, and your current location was in the aforementioned folder as path. In order to admission the file, you need to become through the path binder and and so the to folder, finally arriving at the cats.gif file. The Binder Path is path/to/. The File Name is cats. The File Extension is .gif. So the full path is path/to/cats.gif.

Now permit's say that your current location or current working directory (cwd) is in the to binder of our example binder structure. Instead of referring to the cats.gif by the full path of path/to/cats.gif, the file can be but referenced by the file name and extension cats.gif.

                                / │ ├── path/ |   │ |   ├── to/  ← Your current working directory (cwd) is here |   │   └── cats.gif  ← Accessing this file |   │ |   └── dog_breeds.txt | └── animals.csv                              

Simply what nearly dog_breeds.txt? How would yous access that without using the total path? You tin can use the special characters double-dot (..) to move i directory up. This means that ../dog_breeds.txt will reference the dog_breeds.txt file from the directory of to:

                                / │ ├── path/  ← Referencing this parent folder |   │ |   ├── to/  ← Electric current working directory (cwd) |   │   └── cats.gif |   │ |   └── dog_breeds.txt  ← Accessing this file | └── animals.csv                              

The double-dot (..) can be chained together to traverse multiple directories higher up the current directory. For case, to access animals.csv from the to folder, you would use ../../animals.csv.

Line Endings

Ane problem oft encountered when working with file data is the representation of a new line or line ending. The line ending has its roots from dorsum in the Morse Lawmaking era, when a specific pro-sign was used to communicate the end of a transmission or the end of a line.

Later, this was standardized for teleprinters by both the International System for Standardization (ISO) and the American Standards Clan (ASA). ASA standard states that line endings should utilise the sequence of the Wagon Return (CR or \r) and the Line Feed (LF or \northward) characters (CR+LF or \r\north). The ISO standard however immune for either the CR+LF characters or just the LF graphic symbol.

Windows uses the CR+LF characters to betoken a new line, while Unix and the newer Mac versions utilize just the LF character. This tin can cause some complications when you lot're processing files on an operating system that is different than the file's source. Here's a quick instance. Let'southward say that we examine the file dog_breeds.txt that was created on a Windows system:

                                Pug\r\n Jack Russell Terrier\r\northward English Springer Spaniel\r\n German language Shepherd\r\n Staffordshire Bull Terrier\r\northward Cavalier Rex Charles Spaniel\r\northward Golden Retriever\r\n West Highland White Terrier\r\n Boxer\r\due north Border Terrier\r\n                              

This aforementioned output volition be interpreted on a Unix device differently:

                                Pug\r \due north Jack Russell Terrier\r \northward English Springer Spaniel\r \due north German Shepherd\r \n Staffordshire Bull Terrier\r \northward Cavalier King Charles Spaniel\r \due north Golden Retriever\r \n West Highland White Terrier\r \northward Boxer\r \n Border Terrier\r \n                              

This can make iterating over each line problematic, and you may need to account for situations like this.

Character Encodings

Another mutual problem that you may face is the encoding of the byte data. An encoding is a translation from byte information to human readable characters. This is typically washed by assigning a numerical value to represent a grapheme. The two most mutual encodings are the ASCII and UNICODE Formats. ASCII tin just store 128 characters, while Unicode can incorporate upwards to 1,114,112 characters.

ASCII is actually a subset of Unicode (UTF-8), meaning that ASCII and Unicode share the same numerical to character values. It's of import to note that parsing a file with the wrong character encoding can lead to failures or misrepresentation of the character. For example, if a file was created using the UTF-viii encoding, and you attempt to parse it using the ASCII encoding, if there is a character that is outside of those 128 values, then an error will be thrown.

Opening and Closing a File in Python

When yous desire to piece of work with a file, the first thing to do is to open it. This is done past invoking the open() congenital-in function. open up() has a single required argument that is the path to the file. open() has a unmarried render, the file object:

                                            file                =                open                (                'dog_breeds.txt'                )                          

Afterwards you open up a file, the side by side matter to learn is how to close it.

It'due south of import to remember that it'south your responsibility to close the file. In most cases, upon termination of an application or script, a file volition be closed eventually. However, there is no guarantee when exactly that will happen. This tin can lead to unwanted behavior including resource leaks. It's also a best practise within Python (Pythonic) to brand sure that your lawmaking behaves in a way that is well divers and reduces whatever unwanted behavior.

When you're manipulating a file, there are ii ways that y'all tin can employ to ensure that a file is closed properly, fifty-fifty when encountering an mistake. The beginning manner to close a file is to use the try-finally cake:

                                            reader                =                open                (                'dog_breeds.txt'                )                endeavor                :                # Farther file processing goes here                finally                :                reader                .                close                ()                          

If yous're unfamiliar with what the try-finally block is, check out Python Exceptions: An Introduction.

The second manner to close a file is to apply the with argument:

                                            with                open                (                'dog_breeds.txt'                )                as                reader                :                # Further file processing goes here                          

The with statement automatically takes care of closing the file once information technology leaves the with block, even in cases of error. I highly recommend that you use the with statement as much equally possible, as information technology allows for cleaner lawmaking and makes handling any unexpected errors easier for you.

Most likely, you'll too want to use the 2d positional argument, style. This argument is a string that contains multiple characters to represent how you desire to open the file. The default and most common is 'r', which represents opening the file in read-merely fashion equally a text file:

                                            with                open                (                'dog_breeds.txt'                ,                'r'                )                as                reader                :                # Further file processing goes here                          

Other options for modes are fully documented online, but the most commonly used ones are the following:

Grapheme Meaning
'r' Open for reading (default)
'w' Open for writing, truncating (overwriting) the file first
'rb' or 'wb' Open in binary style (read/write using byte information)

Permit's get back and talk a lilliputian most file objects. A file object is:

"an object exposing a file-oriented API (with methods such as read() or write()) to an underlying resources." (Source)

There are three different categories of file objects:

  • Text files
  • Buffered binary files
  • Raw binary files

Each of these file types are divers in the io module. Hither'southward a quick rundown of how everything lines upwards.

Text File Types

A text file is the near common file that yous'll encounter. Here are some examples of how these files are opened:

                                                  open                  (                  'abc.txt'                  )                  open                  (                  'abc.txt'                  ,                  'r'                  )                  open                  (                  'abc.txt'                  ,                  'w'                  )                              

With these types of files, open() will return a TextIOWrapper file object:

>>>

                                                  >>>                                    file                  =                  open up                  (                  'dog_breeds.txt'                  )                  >>>                                    type                  (                  file                  )                  <form '_io.TextIOWrapper'>                              

This is the default file object returned by open().

Buffered Binary File Types

A buffered binary file type is used for reading and writing binary files. Here are some examples of how these files are opened:

                                                  open up                  (                  'abc.txt'                  ,                  'rb'                  )                  open up                  (                  'abc.txt'                  ,                  'wb'                  )                              

With these types of files, open() will return either a BufferedReader or BufferedWriter file object:

>>>

                                                  >>>                                    file                  =                  open                  (                  'dog_breeds.txt'                  ,                  'rb'                  )                  >>>                                    type                  (                  file                  )                  <class '_io.BufferedReader'>                  >>>                                    file                  =                  open                  (                  'dog_breeds.txt'                  ,                  'wb'                  )                  >>>                                    type                  (                  file                  )                  <class '_io.BufferedWriter'>                              

Raw File Types

A raw file type is:

"more often than not used as a low-level edifice-block for binary and text streams." (Source)

It is therefore not typically used.

Hither's an example of how these files are opened:

                                                  open                  (                  'abc.txt'                  ,                  'rb'                  ,                  buffering                  =                  0                  )                              

With these types of files, open() will render a FileIO file object:

>>>

                                                  >>>                                    file                  =                  open                  (                  'dog_breeds.txt'                  ,                  'rb'                  ,                  buffering                  =                  0                  )                  >>>                                    type                  (                  file                  )                  <class '_io.FileIO'>                              

Reading and Writing Opened Files

Once you've opened up a file, you lot'll want to read or write to the file. First off, let'south cover reading a file. There are multiple methods that can be called on a file object to help yous out:

Method What It Does
.read(size=-1) This reads from the file based on the number of size bytes. If no statement is passed or None or -one is passed, then the unabridged file is read.
.readline(size=-one) This reads at most size number of characters from the line. This continues to the stop of the line and and then wraps back effectually. If no argument is passed or None or -one is passed, then the entire line (or rest of the line) is read.
.readlines() This reads the remaining lines from the file object and returns them as a listing.

Using the same dog_breeds.txt file you used above, let'south go through some examples of how to use these methods. Here's an example of how to open and read the entire file using .read():

>>>

                                            >>>                                with                open                (                'dog_breeds.txt'                ,                'r'                )                as                reader                :                >>>                                # Read & print the entire file                >>>                                print                (                reader                .                read                ())                Pug                Jack Russell Terrier                English Springer Spaniel                German Shepherd                Staffordshire Bull Terrier                Condescending King Charles Spaniel                Golden Retriever                West Highland White Terrier                Boxer                Edge Terrier                          

Here's an example of how to read 5 bytes of a line each time using the Python .readline() method:

>>>

                                            >>>                                with                open up                (                'dog_breeds.txt'                ,                'r'                )                as                reader                :                >>>                                # Read & impress the first 5 characters of the line 5 times                >>>                                print                (                reader                .                readline                (                five                ))                >>>                                # Detect that line is greater than the 5 chars and continues                >>>                                # down the line, reading 5 chars each time until the end of the                >>>                                # line and then "wraps" effectually                >>>                                print                (                reader                .                readline                (                5                ))                >>>                                print                (                reader                .                readline                (                v                ))                >>>                                print                (                reader                .                readline                (                5                ))                >>>                                print                (                reader                .                readline                (                5                ))                Pug                Jack                Russe                ll Te                rrier                          

Hither's an instance of how to read the entire file as a listing using the Python .readlines() method:

>>>

                                            >>>                                f                =                open                (                'dog_breeds.txt'                )                >>>                                f                .                readlines                ()                # Returns a list object                ['Pug\n', 'Jack Russell Terrier\due north', 'English Springer Spaniel\n', 'German language Shepherd\n', 'Staffordshire Bull Terrier\due north', 'Cavalier King Charles Spaniel\n', 'Golden Retriever\n', 'Due west Highland White Terrier\n', 'Boxer\north', 'Border Terrier\n']                          

The in a higher place example tin can also be done by using list() to create a list out of the file object:

>>>

                                            >>>                                f                =                open up                (                'dog_breeds.txt'                )                >>>                                list                (                f                )                ['Pug\n', 'Jack Russell Terrier\n', 'English Springer Spaniel\n', 'German Shepherd\north', 'Staffordshire Bull Terrier\n', 'Cavalier King Charles Spaniel\due north', 'Golden Retriever\n', 'West Highland White Terrier\north', 'Boxer\n', 'Border Terrier\north']                          

Iterating Over Each Line in the File

A common matter to do while reading a file is to iterate over each line. Hither's an case of how to use the Python .readline() method to perform that iteration:

>>>

                                                  >>>                                    with                  open                  (                  'dog_breeds.txt'                  ,                  'r'                  )                  as                  reader                  :                  >>>                                    # Read and print the entire file line past line                  >>>                                    line                  =                  reader                  .                  readline                  ()                  >>>                                    while                  line                  !=                  ''                  :                  # The EOF char is an empty string                  >>>                                    print                  (                  line                  ,                  end                  =                  ''                  )                  >>>                                    line                  =                  reader                  .                  readline                  ()                  Pug                  Jack Russell Terrier                  English Springer Spaniel                  High german Shepherd                  Staffordshire Bull Terrier                  Cavalier Rex Charles Spaniel                  Golden Retriever                  West Highland White Terrier                  Boxer                  Border Terrier                              

Another fashion y'all could iterate over each line in the file is to utilize the Python .readlines() method of the file object. Remember, .readlines() returns a listing where each chemical element in the list represents a line in the file:

>>>

                                                  >>>                                    with                  open                  (                  'dog_breeds.txt'                  ,                  'r'                  )                  as                  reader                  :                  >>>                                    for                  line                  in                  reader                  .                  readlines                  ():                  >>>                                    print                  (                  line                  ,                  terminate                  =                  ''                  )                  Pug                  Jack Russell Terrier                  English language Springer Spaniel                  German Shepherd                  Staffordshire Bull Terrier                  Condescending King Charles Spaniel                  Golden Retriever                  West Highland White Terrier                  Boxer                  Border Terrier                              

However, the above examples tin be farther simplified past iterating over the file object itself:

>>>

                                                  >>>                                    with                  open                  (                  'dog_breeds.txt'                  ,                  'r'                  )                  as                  reader                  :                  >>>                                    # Read and print the entire file line by line                  >>>                                    for                  line                  in                  reader                  :                  >>>                                    impress                  (                  line                  ,                  end                  =                  ''                  )                  Pug                  Jack Russell Terrier                  English language Springer Spaniel                  German Shepherd                  Staffordshire Bull Terrier                  Condescending King Charles Spaniel                  Golden Retriever                  Due west Highland White Terrier                  Boxer                  Border Terrier                              

This final arroyo is more Pythonic and tin can be quicker and more memory efficient. Therefore, it is suggested you apply this instead.

At present permit'southward swoop into writing files. As with reading files, file objects have multiple methods that are useful for writing to a file:

Method What It Does
.write(string) This writes the cord to the file.
.writelines(seq) This writes the sequence to the file. No line endings are appended to each sequence item. Information technology's up to you to add the appropriate line ending(due south).

Hither's a quick example of using .write() and .writelines():

                                                  with                  open up                  (                  'dog_breeds.txt'                  ,                  'r'                  )                  as                  reader                  :                  # Note: readlines doesn't trim the line endings                  dog_breeds                  =                  reader                  .                  readlines                  ()                  with                  open up                  (                  'dog_breeds_reversed.txt'                  ,                  'west'                  )                  every bit                  writer                  :                  # Alternatively you lot could apply                  # writer.writelines(reversed(dog_breeds))                  # Write the dog breeds to the file in reversed order                  for                  brood                  in                  reversed                  (                  dog_breeds                  ):                  writer                  .                  write                  (                  brood                  )                              

Working With Bytes

Sometimes, you may need to piece of work with files using byte strings. This is done past calculation the 'b' character to the mode argument. All of the same methods for the file object apply. However, each of the methods look and render a bytes object instead:

>>>

                                                  >>>                                    with                  open                  (                  'dog_breeds.txt'                  ,                  'rb'                  )                  as                  reader                  :                  >>>                                    print                  (                  reader                  .                  readline                  ())                  b'Pug\n'                              

Opening a text file using the b flag isn't that interesting. Allow'south say we take this cute picture of a Jack Russell Terrier (jack_russell.png):

A cute picture of a Jack Russell Terrier
Image: CC BY 3.0 (https://creativecommons.org/licenses/by/3.0)], from Wikimedia Commons

You tin can actually open that file in Python and examine the contents! Since the .png file format is well defined, the header of the file is 8 bytes broken up like this:

Value Interpretation
0x89 A "magic" number to indicate that this is the outset of a PNG
0x50 0x4E 0x47 PNG in ASCII
0x0D 0x0A A DOS style line catastrophe \r\n
0x1A A DOS mode EOF graphic symbol
0x0A A Unix style line ending \due north

Certain enough, when you open the file and read these bytes individually, you lot can see that this is indeed a .png header file:

>>>

                                                  >>>                                    with                  open                  (                  'jack_russell.png'                  ,                  'rb'                  )                  as                  byte_reader                  :                  >>>                                    print                  (                  byte_reader                  .                  read                  (                  ane                  ))                  >>>                                    print                  (                  byte_reader                  .                  read                  (                  3                  ))                  >>>                                    impress                  (                  byte_reader                  .                  read                  (                  2                  ))                  >>>                                    print                  (                  byte_reader                  .                  read                  (                  1                  ))                  >>>                                    print                  (                  byte_reader                  .                  read                  (                  1                  ))                  b'\x89'                  b'PNG'                  b'\r\north'                  b'\x1a'                  b'\north'                              

A Total Example: dos2unix.py

Allow's bring this whole thing home and look at a full example of how to read and write to a file. The following is a dos2unix like tool that will convert a file that contains line endings of \r\northward to \due north.

This tool is broken up into 3 major sections. The first is str2unix(), which converts a string from \r\north line endings to \northward. The 2d is dos2unix(), which converts a cord that contains \r\n characters into \n. dos2unix() calls str2unix() internally. Finally, there'south the __main__ block, which is called only when the file is executed as a script. Think of it as the principal role plant in other programming languages.

                                                  """                  A uncomplicated script and library to convert files or strings from dos like                  line endings with Unix like line endings.                  """                  import                  argparse                  import                  bone                  def                  str2unix                  (                  input_str                  :                  str                  )                  ->                  str                  :                  r                  """                                      Converts the string from \r\n line endings to \n                                      Parameters                                      ----------                                      input_str                                      The string whose line endings will be converted                                      Returns                                      -------                                      The converted cord                                      """                  r_str                  =                  input_str                  .                  supercede                  (                  '                  \r\n                  '                  ,                  '                  \n                  '                  )                  return                  r_str                  def                  dos2unix                  (                  source_file                  :                  str                  ,                  dest_file                  :                  str                  ):                  """                                      Converts a file that contains Dos like line endings into Unix like                                      Parameters                                      ----------                                      source_file                                      The path to the source file to exist converted                                      dest_file                                      The path to the converted file for output                                      """                  # NOTE: Could add file existence checking and file overwriting                  # protection                  with                  open                  (                  source_file                  ,                  'r'                  )                  as                  reader                  :                  dos_content                  =                  reader                  .                  read                  ()                  unix_content                  =                  str2unix                  (                  dos_content                  )                  with                  open                  (                  dest_file                  ,                  'due west'                  )                  every bit                  writer                  :                  writer                  .                  write                  (                  unix_content                  )                  if                  __name__                  ==                  "__main__"                  :                  # Create our Argument parser and set its description                  parser                  =                  argparse                  .                  ArgumentParser                  (                  description                  =                  "Script that converts a DOS like file to an Unix like file"                  ,                  )                  # Add the arguments:                  #   - source_file: the source file we want to convert                  #   - dest_file: the destination where the output should go                  # Notation: the utilize of the argument type of argparse.FileType could                  # streamline some things                  parser                  .                  add_argument                  (                  'source_file'                  ,                  help                  =                  'The location of the source '                  )                  parser                  .                  add_argument                  (                  '--dest_file'                  ,                  help                  =                  'Location of dest file (default: source_file appended with `_unix`'                  ,                  default                  =                  None                  )                  # Parse the args (argparse automatically grabs the values from                  # sys.argv)                  args                  =                  parser                  .                  parse_args                  ()                  s_file                  =                  args                  .                  source_file                  d_file                  =                  args                  .                  dest_file                  # If the destination file wasn't passed, and then presume we desire to                  # create a new file based on the former i                  if                  d_file                  is                  None                  :                  file_path                  ,                  file_extension                  =                  bone                  .                  path                  .                  splitext                  (                  s_file                  )                  d_file                  =                  f                  '                  {                  file_path                  }                  _unix                  {                  file_extension                  }                  '                  dos2unix                  (                  s_file                  ,                  d_file                  )                              

Tips and Tricks

Now that you lot've mastered the basics of reading and writing files, here are some tips and tricks to aid you grow your skills.

__file__

The __file__ attribute is a special attribute of modules, like to __name__. It is:

"the pathname of the file from which the module was loaded, if it was loaded from a file." (Source

Here's a existent world case. In i of my past jobs, I did multiple tests for a hardware device. Each test was written using a Python script with the examination script file name used as a title. These scripts would then exist executed and could print their condition using the __file__ special attribute. Hither'due south an example folder structure:

                                projection/ | ├── tests/ |   ├── test_commanding.py |   ├── test_power.py |   ├── test_wireHousing.py |   └── test_leds.py | └── main.py                              

Running main.py produces the following:

                                >>> python main.py tests/test_commanding.py Started: tests/test_commanding.py Passed! tests/test_power.py Started: tests/test_power.py Passed! tests/test_wireHousing.py Started: tests/test_wireHousing.py Failed! tests/test_leds.py Started: tests/test_leds.py Passed!                              

I was able to run and get the condition of all my tests dynamically through utilise of the __file__ special aspect.

Appending to a File

Sometimes, you may desire to append to a file or start writing at the end of an already populated file. This is easily washed by using the 'a' graphic symbol for the mode statement:

                                                  with                  open                  (                  'dog_breeds.txt'                  ,                  'a'                  )                  as                  a_writer                  :                  a_writer                  .                  write                  (                  '                  \northward                  Beagle'                  )                              

When you examine dog_breeds.txt again, you lot'll meet that the beginning of the file is unchanged and Beagle is at present added to the cease of the file:

>>>

                                                  >>>                                    with                  open                  (                  'dog_breeds.txt'                  ,                  'r'                  )                  as                  reader                  :                  >>>                                    print                  (                  reader                  .                  read                  ())                  Pug                  Jack Russell Terrier                  English Springer Spaniel                  German Shepherd                  Staffordshire Bull Terrier                  Cavalier Rex Charles Spaniel                  Golden Retriever                  Westward Highland White Terrier                  Boxer                  Border Terrier                  Beagle                              

Working With 2 Files at the Aforementioned Time

At that place are times when you may want to read a file and write to some other file at the aforementioned fourth dimension. If you utilise the example that was shown when yous were learning how to write to a file, it tin actually be combined into the following:

                                                  d_path                  =                  'dog_breeds.txt'                  d_r_path                  =                  'dog_breeds_reversed.txt'                  with                  open up                  (                  d_path                  ,                  'r'                  )                  as                  reader                  ,                  open                  (                  d_r_path                  ,                  'w'                  )                  equally                  writer                  :                  dog_breeds                  =                  reader                  .                  readlines                  ()                  writer                  .                  writelines                  (                  reversed                  (                  dog_breeds                  ))                              

Creating Your Own Context Manager

In that location may come a time when you'll demand finer command of the file object by placing it inside a custom class. When you practice this, using the with statement tin can no longer be used unless you lot add a few magic methods: __enter__ and __exit__. By adding these, you'll have created what'due south called a context director.

__enter__() is invoked when calling the with statement. __exit__() is called upon exiting from the with argument block.

Here's a template that you can employ to brand your custom class:

                                                  class                  my_file_reader                  ():                  def                  __init__                  (                  self                  ,                  file_path                  ):                  self                  .                  __path                  =                  file_path                  self                  .                  __file_object                  =                  None                  def                  __enter__                  (                  cocky                  ):                  self                  .                  __file_object                  =                  open                  (                  cocky                  .                  __path                  )                  render                  self                  def                  __exit__                  (                  self                  ,                  type                  ,                  val                  ,                  tb                  ):                  self                  .                  __file_object                  .                  close                  ()                  # Additional methods implemented below                              

At present that you've got your custom form that is now a context manager, you can use it similarly to the open() built-in:

                                                  with                  my_file_reader                  (                  'dog_breeds.txt'                  )                  as                  reader                  :                  # Perform custom class operations                  pass                              

Hither's a expert example. Think the beautiful Jack Russell paradigm we had? Perchance yous want to open other .png files but don't want to parse the header file each time. Here's an instance of how to do this. This example likewise uses custom iterators. If you lot're not familiar with them, bank check out Python Iterators:

                                                  class                  PngReader                  ():                  # Every .png file contains this in the header.  Use it to verify                  # the file is indeed a .png.                  _expected_magic                  =                  b                  '                  \x89                  PNG                  \r\n\x1a\n                  '                  def                  __init__                  (                  self                  ,                  file_path                  ):                  # Ensure the file has the right extension                  if                  not                  file_path                  .                  endswith                  (                  '.png'                  ):                  raise                  NameError                  (                  "File must exist a '.png' extension"                  )                  cocky                  .                  __path                  =                  file_path                  self                  .                  __file_object                  =                  None                  def                  __enter__                  (                  self                  ):                  self                  .                  __file_object                  =                  open                  (                  cocky                  .                  __path                  ,                  'rb'                  )                  magic                  =                  self                  .                  __file_object                  .                  read                  (                  8                  )                  if                  magic                  !=                  self                  .                  _expected_magic                  :                  raise                  TypeError                  (                  "The File is not a properly formatted .png file!"                  )                  return                  cocky                  def                  __exit__                  (                  self                  ,                  type                  ,                  val                  ,                  tb                  ):                  self                  .                  __file_object                  .                  shut                  ()                  def                  __iter__                  (                  self                  ):                  # This and __next__() are used to create a custom iterator                  # See https://dbader.org/weblog/python-iterators                  return                  self                  def                  __next__                  (                  self                  ):                  # Read the file in "Chunks"                  # Run into https://en.wikipedia.org/wiki/Portable_Network_Graphics#%22Chunks%22_within_the_file                  initial_data                  =                  cocky                  .                  __file_object                  .                  read                  (                  4                  )                  # The file hasn't been opened or reached EOF.  This means nosotros                  # can't go whatsoever further so stop the iteration by raising the                  # StopIteration.                  if                  self                  .                  __file_object                  is                  None                  or                  initial_data                  ==                  b                  ''                  :                  raise                  StopIteration                  else                  :                  # Each chunk has a len, type, information (based on len) and crc                  # Catch these values and return them as a tuple                  chunk_len                  =                  int                  .                  from_bytes                  (                  initial_data                  ,                  byteorder                  =                  'big'                  )                  chunk_type                  =                  self                  .                  __file_object                  .                  read                  (                  four                  )                  chunk_data                  =                  self                  .                  __file_object                  .                  read                  (                  chunk_len                  )                  chunk_crc                  =                  self                  .                  __file_object                  .                  read                  (                  iv                  )                  return                  chunk_len                  ,                  chunk_type                  ,                  chunk_data                  ,                  chunk_crc                              

You can now open up .png files and properly parse them using your custom context manager:

>>>

                                                  >>>                                    with                  PngReader                  (                  'jack_russell.png'                  )                  as                  reader                  :                  >>>                                    for                  50                  ,                  t                  ,                  d                  ,                  c                  in                  reader                  :                  >>>                                    print                  (                  f                  "                  {                  l                  :                  05                  }                  ,                                    {                  t                  }                  ,                                    {                  c                  }                  "                  )                  00013, b'IHDR', b'v\x121k'                  00001, b'sRGB', b'\xae\xce\x1c\xe9'                  00009, b'pHYs', b'(<]\x19'                  00345, b'iTXt', b"50\xc2'Y"                  16384, b'IDAT', b'i\x99\x0c('                  16384, b'IDAT', b'\xb3\xfa\x9a$'                  16384, b'IDAT', b'\xff\xbf\xd1\n'                  16384, b'IDAT', b'\xc3\x9c\xb1}'                  16384, b'IDAT', b'\xe3\x02\xba\x91'                  16384, b'IDAT', b'\xa0\xa99='                  16384, b'IDAT', b'\xf4\x8b.\x92'                  16384, b'IDAT', b'\x17i\xfc\xde'                  16384, b'IDAT', b'\x8fb\x0e\xe4'                  16384, b'IDAT', b')three={'                  01040, b'IDAT', b'\xd6\xb8\xc1\x9f'                  00000, b'IEND', b'\xaeB`\x82'                              

Don't Re-Invent the Snake

There are mutual situations that you lot may see while working with files. Most of these cases can be handled using other modules. Two common file types y'all may need to work with are .csv and .json. Real Python has already put together some great manufactures on how to handle these:

  • Reading and Writing CSV Files in Python
  • Working With JSON Data in Python

Additionally, there are built-in libraries out there that you can use to assistance yous:

  • moving ridge : read and write WAV files (audio)
  • aifc : read and write AIFF and AIFC files (audio)
  • sunau : read and write Sun AU files
  • tarfile : read and write tar archive files
  • zipfile : work with ZIP archives
  • configparser : easily create and parse configuration files
  • xml.etree.ElementTree : create or read XML based files
  • msilib : read and write Microsoft Installer files
  • plistlib : generate and parse Mac OS X .plist files

There are plenty more out there. Additionally there are fifty-fifty more third party tools available on PyPI. Some popular ones are the following:

  • PyPDF2 : PDF toolkit
  • xlwings : read and write Excel files
  • Pillow : image reading and manipulation

You lot're a File Sorcerer Harry!

Y'all did it! Yous now know how to work with files with Python, including some avant-garde techniques. Working with files in Python should now be easier than ever and is a rewarding feeling when you start doing it.

In this tutorial you've learned:

  • What a file is
  • How to open up and close files properly
  • How to read and write files
  • Some advanced techniques when working with files
  • Some libraries to work with common file types

If y'all have any questions, striking united states upwards in the comments.

Spotter Now This tutorial has a related video form created by the Real Python squad. Sentry it together with the written tutorial to deepen your agreement: Reading and Writing Files in Python