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

1 of the virtually common tasks that you lot tin exercise with Python is reading and writing files. Whether it'south writing to a elementary text file, reading a complicated server log, or even analyzing raw byte data, all of these situations require reading or writing a file.

In this tutorial, you'll learn:

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

This tutorial is mainly for beginner to intermediate Pythonistas, simply there are some tips in here that more than avant-garde programmers may appreciate every bit well.

What Is a File?

Before we tin can go into how to piece of work with files in Python, it's of import to sympathize what exactly a file is and how modern operating systems handle some of their aspects.

At its core, a file is a contiguous prepare of bytes used to store information. This data is organized in a specific format and can be anything every bit simple as a text file or every bit complicated every bit a program executable. In the finish, these byte files are then translated into binary one and 0 for easier processing past the reckoner.

Files on near modern file systems are composed of iii principal parts:

  1. Header: metadata about the contents of the file (file proper name, size, type, and so on)
  2. Data: contents of the file as written by the creator or editor
  3. End of file (EOF): special graphic symbol that indicates the end of the file
The file format with the header on top, data contents in the middle and the footer on the bottom.

What this data represents depends on the format specification used, which is typically represented by an extension. For example, a file that has an extension of .gif virtually probable conforms to the Graphics Interchange Format specification. There are hundreds, if not thousands, of file extensions out there. For this tutorial, yous'll only deal with .txt or .csv file extensions.

File Paths

When you access a file on an operating system, a file path is required. The file path is a cord that represents the location of a file. Information technology'south broken up into three major parts:

  1. Folder Path: the file binder location on the file arrangement where subsequent folders are separated past a forrard slash / (Unix) or backslash \ (Windows)
  2. File Name: the bodily name of the file
  3. Extension: the end of the file path pre-pended with a period (.) used to indicate the file type

Here'south a quick example. Let's say you accept a file located inside a file structure similar this:

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

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

At present let'southward say that your current location or current working directory (cwd) is in the to folder of our example folder structure. Instead of referring to the cats.gif past the total path of path/to/cats.gif, the file can be simply referenced past 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                              

Merely what nearly dog_breeds.txt? How would you access that without using the full path? You can use the special characters double-dot (..) to move ane directory upward. This means that ../dog_breeds.txt will reference the dog_breeds.txt file from the directory of to:

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

The double-dot (..) can exist chained together to traverse multiple directories above the current directory. For instance, to access animals.csv from the to folder, you would utilise ../../animals.csv.

Line Endings

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

Afterwards, this was standardized for teleprinters by both the International Organization for Standardization (ISO) and the American Standards Association (ASA). ASA standard states that line endings should use the sequence of the Carriage Return (CR or \r) and the Line Feed (LF or \n) characters (CR+LF or \r\northward). The ISO standard however immune for either the CR+LF characters or simply the LF grapheme.

Windows uses the CR+LF characters to bespeak a new line, while Unix and the newer Mac versions use just the LF character. This can crusade some complications when you're processing files on an operating organization that is dissimilar than the file'south source. Here'southward a quick instance. Let's say that nosotros examine the file dog_breeds.txt that was created on a Windows organisation:

                                Pug\r\n Jack Russell Terrier\r\n English Springer Spaniel\r\north German Shepherd\r\n Staffordshire Bull Terrier\r\n Cavalier King Charles Spaniel\r\n Golden Retriever\r\n Westward Highland White Terrier\r\n Boxer\r\n Edge Terrier\r\north                              

This same output will be interpreted on a Unix device differently:

                                Pug\r \northward Jack Russell Terrier\r \n English Springer Spaniel\r \n German Shepherd\r \northward Staffordshire Balderdash Terrier\r \n Cavalier King Charles Spaniel\r \due north Golden Retriever\r \north West Highland White Terrier\r \n Boxer\r \n Edge 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 data to human being readable characters. This is typically washed by assigning a numerical value to stand for a graphic symbol. The two most common encodings are the ASCII and UNICODE Formats. ASCII can only store 128 characters, while Unicode tin contain up to 1,114,112 characters.

ASCII is really a subset of Unicode (UTF-eight), meaning that ASCII and Unicode share the same numerical to grapheme values. It's important to notation that parsing a file with the incorrect graphic symbol encoding can lead to failures or misrepresentation of the graphic symbol. For example, if a file was created using the UTF-eight encoding, and yous attempt to parse it using the ASCII encoding, if there is a character that is outside of those 128 values, so an error will be thrown.

Opening and Closing a File in Python

When y'all want to work with a file, the get-go matter to do is to open it. This is washed past invoking the open() congenital-in function. open up() has a single required argument that is the path to the file. open() has a single return, the file object:

                                            file                =                open up                (                'dog_breeds.txt'                )                          

After you open a file, the next matter to learn is how to close it.

It'south important to remember that it'south your responsibility to close the file. In virtually cases, upon termination of an application or script, a file will be closed eventually. All the same, there is no guarantee when exactly that will happen. This can lead to unwanted behavior including resource leaks. It's also a best practise within Python (Pythonic) to make sure that your lawmaking behaves in a way that is well defined and reduces whatsoever unwanted behavior.

When y'all're manipulating a file, there are two means that you can use to ensure that a file is closed properly, even when encountering an error. The kickoff manner to close a file is to use the effort-finally block:

                                            reader                =                open                (                'dog_breeds.txt'                )                endeavour                :                # Further file processing goes hither                finally                :                reader                .                close                ()                          

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

The second way to close a file is to use the with statement:

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

The with argument automatically takes intendance of endmost the file once it leaves the with cake, even in cases of error. I highly recommend that y'all employ the with statement every bit much equally possible, as it allows for cleaner code and makes handling whatsoever unexpected errors easier for y'all.

Most likely, you'll also want to use the second positional argument, style. This argument is a string that contains multiple characters to represent how you desire to open up the file. The default and most mutual is 'r', which represents opening the file in read-only mode as a text file:

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

Other options for modes are fully documented online, but the most ordinarily used ones are the post-obit:

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

Permit'southward get dorsum and talk a petty about file objects. A file object is:

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

In that location are three different categories of file objects:

  • Text files
  • Buffered binary files
  • Raw binary files

Each of these file types are defined in the io module. Here'due south a quick rundown of how everything lines up.

Text File Types

A text file is the nigh mutual file that you'll encounter. Here are some examples of how these files are opened:

                                                  open up                  (                  'abc.txt'                  )                  open                  (                  'abc.txt'                  ,                  'r'                  )                  open up                  (                  'abc.txt'                  ,                  'westward'                  )                              

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

>>>

                                                  >>>                                    file                  =                  open                  (                  '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                  (                  'abc.txt'                  ,                  'rb'                  )                  open                  (                  'abc.txt'                  ,                  'wb'                  )                              

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

>>>

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

Raw File Types

A raw file type is:

"generally used as a low-level edifice-cake for binary and text streams." (Source)

It is therefore not typically used.

Here's an instance of how these files are opened:

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

With these types of files, open() volition return 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'll want to read or write to the file. First off, let's comprehend reading a file. There are multiple methods that can exist called on a file object to assist you out:

Method What Information technology Does
.read(size=-ane) This reads from the file based on the number of size bytes. If no argument is passed or None or -1 is passed, so the entire file is read.
.readline(size=-1) This reads at well-nigh size number of characters from the line. This continues to the end of the line and then wraps back around. If no argument is passed or None or -one is passed, then the unabridged line (or residue of the line) is read.
.readlines() This reads the remaining lines from the file object and returns them as a list.

Using the same dog_breeds.txt file you used higher up, let's get 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                >>>                                impress                (                reader                .                read                ())                Pug                Jack Russell Terrier                English Springer Spaniel                High german Shepherd                Staffordshire Balderdash Terrier                Cavalier Male monarch Charles Spaniel                Golden Retriever                West Highland White Terrier                Boxer                Border Terrier                          

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

>>>

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

Hither'south an case of how to read the entire file as a list using the Python .readlines() method:

>>>

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

The above instance tin also be done past using list() to create a list out of the file object:

>>>

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

Iterating Over Each Line in the File

A common affair to practice while reading a file is to iterate over each line. Here'due south an example of how to apply the Python .readline() method to perform that iteration:

>>>

                                                  >>>                                    with                  open                  (                  'dog_breeds.txt'                  ,                  'r'                  )                  as                  reader                  :                  >>>                                    # Read and impress the entire file line by 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                  German Shepherd                  Staffordshire Bull Terrier                  Cavalier Male monarch Charles Spaniel                  Golden Retriever                  W Highland White Terrier                  Boxer                  Edge Terrier                              

Another way you could iterate over each line in the file is to use the Python .readlines() method of the file object. Recall, .readlines() returns a list where each 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                  ,                  cease                  =                  ''                  )                  Pug                  Jack Russell Terrier                  English Springer Spaniel                  German Shepherd                  Staffordshire Bull Terrier                  Cavalier Male monarch Charles Spaniel                  Gilt Retriever                  W Highland White Terrier                  Boxer                  Border Terrier                              

Nevertheless, the to a higher place examples can be further simplified by 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                  :                  >>>                                    print                  (                  line                  ,                  end                  =                  ''                  )                  Pug                  Jack Russell Terrier                  English Springer Spaniel                  German Shepherd                  Staffordshire Bull Terrier                  Cavalier King Charles Spaniel                  Gilt Retriever                  West Highland White Terrier                  Boxer                  Border Terrier                              

This final approach is more than Pythonic and can be quicker and more retentiveness efficient. Therefore, it is suggested you lot use this instead.

Now permit'southward dive 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 string to the file.
.writelines(seq) This writes the sequence to the file. No line endings are appended to each sequence detail. It'south up to you to add the appropriate line ending(due south).

Here's a quick case of using .write() and .writelines():

                                                  with                  open                  (                  'dog_breeds.txt'                  ,                  'r'                  )                  equally                  reader                  :                  # Note: readlines doesn't trim the line endings                  dog_breeds                  =                  reader                  .                  readlines                  ()                  with                  open                  (                  'dog_breeds_reversed.txt'                  ,                  'westward'                  )                  as                  author                  :                  # Alternatively you could use                  # writer.writelines(reversed(dog_breeds))                  # Write the domestic dog breeds to the file in reversed social club                  for                  brood                  in                  reversed                  (                  dog_breeds                  ):                  author                  .                  write                  (                  breed                  )                              

Working With Bytes

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

>>>

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

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

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

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

Value Interpretation
0x89 A "magic" number to indicate that this is the showtime of a PNG
0x50 0x4E 0x47 PNG in ASCII
0x0D 0x0A A DOS style line ending \r\n
0x1A A DOS style EOF grapheme
0x0A A Unix style line ending \northward

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

>>>

                                                  >>>                                    with                  open up                  (                  'jack_russell.png'                  ,                  'rb'                  )                  as                  byte_reader                  :                  >>>                                    print                  (                  byte_reader                  .                  read                  (                  1                  ))                  >>>                                    print                  (                  byte_reader                  .                  read                  (                  iii                  ))                  >>>                                    print                  (                  byte_reader                  .                  read                  (                  ii                  ))                  >>>                                    print                  (                  byte_reader                  .                  read                  (                  1                  ))                  >>>                                    print                  (                  byte_reader                  .                  read                  (                  i                  ))                  b'\x89'                  b'PNG'                  b'\r\n'                  b'\x1a'                  b'\northward'                              

A Total Example: dos2unix.py

Let's bring this whole thing home and wait at a full example of how to read and write to a file. The post-obit is a dos2unix like tool that will convert a file that contains line endings of \r\due north to \n.

This tool is broken upwards into 3 major sections. The start is str2unix(), which converts a cord from \r\n line endings to \n. The second is dos2unix(), which converts a string that contains \r\n characters into \due north. dos2unix() calls str2unix() internally. Finally, in that location's the __main__ block, which is called only when the file is executed as a script. Think of information technology every bit the chief function found in other programming languages.

                                                  """                  A uncomplicated script and library to convert files or strings from dos similar                  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                  .                  replace                  (                  '                  \r\due north                  '                  ,                  '                  \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 be 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'                  )                  equally                  reader                  :                  dos_content                  =                  reader                  .                  read                  ()                  unix_content                  =                  str2unix                  (                  dos_content                  )                  with                  open                  (                  dest_file                  ,                  'westward'                  )                  as                  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 similar file to an Unix like file"                  ,                  )                  # Add the arguments:                  #   - source_file: the source file nosotros desire to convert                  #   - dest_file: the destination where the output should go                  # Notation: the use of the statement type of argparse.FileType could                  # streamline some things                  parser                  .                  add_argument                  (                  'source_file'                  ,                  assistance                  =                  '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, then assume nosotros want to                  # create a new file based on the old one                  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 y'all've mastered the nuts of reading and writing files, here are some tips and tricks to help y'all abound 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 real world instance. In one of my by jobs, I did multiple tests for a hardware device. Each test was written using a Python script with the exam script file name used as a title. These scripts would so be executed and could print their status using the __file__ special attribute. Here's an example folder structure:

                                project/ | ├── tests/ |   ├── test_commanding.py |   ├── test_power.py |   ├── test_wireHousing.py |   └── test_leds.py | └── master.py                              

Running main.py produces the following:

                                >>> python primary.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 become the status of all my tests dynamically through employ of the __file__ special aspect.

Appending to a File

Sometimes, yous may want to append to a file or commencement writing at the cease of an already populated file. This is hands done by using the 'a' grapheme for the manner argument:

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

When you examine dog_breeds.txt again, you'll come across that the beginning of the file is unchanged and Beagle is now added to the end of the file:

>>>

                                                  >>>                                    with                  open                  (                  'dog_breeds.txt'                  ,                  'r'                  )                  every bit                  reader                  :                  >>>                                    impress                  (                  reader                  .                  read                  ())                  Pug                  Jack Russell Terrier                  English Springer Spaniel                  German Shepherd                  Staffordshire Bull Terrier                  Cavalier King Charles Spaniel                  Golden Retriever                  W Highland White Terrier                  Boxer                  Border Terrier                  Beagle                              

Working With Two Files at the Same Time

There are times when you may want to read a file and write to another file at the same time. If yous use the example that was shown when you were learning how to write to a file, information technology can actually be combined into the following:

                                                  d_path                  =                  'dog_breeds.txt'                  d_r_path                  =                  'dog_breeds_reversed.txt'                  with                  open                  (                  d_path                  ,                  'r'                  )                  as                  reader                  ,                  open                  (                  d_r_path                  ,                  'west'                  )                  every bit                  writer                  :                  dog_breeds                  =                  reader                  .                  readlines                  ()                  writer                  .                  writelines                  (                  reversed                  (                  dog_breeds                  ))                              

Creating Your Own Context Manager

There may come up a time when you'll need finer control of the file object by placing it inside a custom class. When you practise this, using the with statement tin can no longer be used unless you add a few magic methods: __enter__ and __exit__. By adding these, you'll have created what's chosen a context manager.

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

Here's a template that you can utilize to make your custom class:

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

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

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

Here's a good example. Remember the cute Jack Russell image nosotros had? Perhaps y'all desire to open other .png files simply don't want to parse the header file each time. Here'southward an example of how to do this. This instance besides uses custom iterators. If you're not familiar with them, 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"                  )                  self                  .                  __path                  =                  file_path                  self                  .                  __file_object                  =                  None                  def                  __enter__                  (                  self                  ):                  self                  .                  __file_object                  =                  open                  (                  cocky                  .                  __path                  ,                  'rb'                  )                  magic                  =                  self                  .                  __file_object                  .                  read                  (                  eight                  )                  if                  magic                  !=                  cocky                  .                  _expected_magic                  :                  raise                  TypeError                  (                  "The File is not a properly formatted .png file!"                  )                  return                  self                  def                  __exit__                  (                  cocky                  ,                  type                  ,                  val                  ,                  tb                  ):                  self                  .                  __file_object                  .                  close                  ()                  def                  __iter__                  (                  self                  ):                  # This and __next__() are used to create a custom iterator                  # See https://dbader.org/blog/python-iterators                  render                  self                  def                  __next__                  (                  self                  ):                  # Read the file in "Chunks"                  # See https://en.wikipedia.org/wiki/Portable_Network_Graphics#%22Chunks%22_within_the_file                  initial_data                  =                  self                  .                  __file_object                  .                  read                  (                  4                  )                  # The file hasn't been opened or reached EOF.  This means we                  # can't go whatsoever further so stop the iteration past raising the                  # StopIteration.                  if                  cocky                  .                  __file_object                  is                  None                  or                  initial_data                  ==                  b                  ''                  :                  enhance                  StopIteration                  else                  :                  # Each chunk has a len, type, data (based on len) and crc                  # Take hold of these values and return them equally a tuple                  chunk_len                  =                  int                  .                  from_bytes                  (                  initial_data                  ,                  byteorder                  =                  'large'                  )                  chunk_type                  =                  self                  .                  __file_object                  .                  read                  (                  four                  )                  chunk_data                  =                  self                  .                  __file_object                  .                  read                  (                  chunk_len                  )                  chunk_crc                  =                  cocky                  .                  __file_object                  .                  read                  (                  4                  )                  return                  chunk_len                  ,                  chunk_type                  ,                  chunk_data                  ,                  chunk_crc                              

You tin at present open .png files and properly parse them using your custom context managing director:

>>>

                                                  >>>                                    with                  PngReader                  (                  'jack_russell.png'                  )                  as                  reader                  :                  >>>                                    for                  l                  ,                  t                  ,                  d                  ,                  c                  in                  reader                  :                  >>>                                    print                  (                  f                  "                  {                  50                  :                  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"L\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')3={'                  01040, b'IDAT', b'\xd6\xb8\xc1\x9f'                  00000, b'IEND', b'\xaeB`\x82'                              

Don't Re-Invent the Serpent

There are common situations that you may come across while working with files. Nigh of these cases tin can be handled using other modules. Two common file types you 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, in that location are born libraries out at that place that yous can use to help y'all:

  • wave : read and write WAV files (sound)
  • aifc : read and write AIFF and AIFC files (sound)
  • sunau : read and write Lord's day AU files
  • tarfile : read and write tar archive files
  • zipfile : piece of work with Cipher 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 Bone X .plist files

There are plenty more out there. Additionally in that location are even more than third party tools available on PyPI. Some popular ones are the following:

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

You're a File Magician Harry!

You did it! You now know how to piece of work with files with Python, including some advanced 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 and close files properly
  • How to read and write files
  • Some avant-garde techniques when working with files
  • Some libraries to work with common file types

If you have any questions, hit united states up in the comments.

Lookout man Now This tutorial has a related video grade created past the Real Python squad. Lookout man information technology together with the written tutorial to deepen your understanding: Reading and Writing Files in Python