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

One of the about common tasks that you lot can do with Python is reading and writing files. Whether it'southward writing to a simple 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 lot'll learn:

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

This tutorial is mainly for beginner to intermediate Pythonistas, but there are some tips in here that more advanced programmers may capeesh every bit well.

What Is a File?

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

At its core, a file is a face-to-face set of bytes used to store information. This data is organized in a specific format and can exist anything equally simple as a text file or as complicated as a programme executable. In the end, these byte files are then translated into binary 1 and 0 for easier processing by the calculator.

Files on most modern file systems are composed of three principal parts:

  1. Header: metadata most the contents of the file (file name, size, blazon, and and so on)
  2. Data: contents of the file every bit written by the creator or editor
  3. End of file (EOF): special grapheme 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 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 almost 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 deal with .txt or .csv file extensions.

File Paths

When you admission a file on an operating system, a file path is required. The file path is a string that represents the location of a file. It's broken up into three major parts:

  1. Binder Path: the file binder location on the file system where subsequent folders are separated by a forward slash / (Unix) or backslash \ (Windows)
  2. File Name: the actual name of the file
  3. Extension: the stop of the file path pre-pended with a period (.) used to indicate the file type

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

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

Let's say you wanted to access the cats.gif file, and your current location was in the aforementioned folder as path. In lodge to access the file, you lot need to go through the path binder and then the to binder, 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 full path is path/to/cats.gif.

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

But what about dog_breeds.txt? How would you access that without using the total path? Yous can use the special characters double-dot (..) to move one directory up. This means that ../dog_breeds.txt volition 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 exist chained together to traverse multiple directories above the current directory. For example, to access animals.csv from the to folder, you would use ../../animals.csv.

Line Endings

One problem often 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 Code 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 Organisation for Standardization (ISO) and the American Standards Clan (ASA). ASA standard states that line endings should employ 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 allowed for either the CR+LF characters or just the LF graphic symbol.

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

                                Pug\r\n Jack Russell Terrier\r\n English Springer Spaniel\r\n German Shepherd\r\n Staffordshire Bull Terrier\r\north Condescending Rex Charles Spaniel\r\n Gilt Retriever\r\n West Highland White Terrier\r\n Boxer\r\n Border Terrier\r\north                              

This same output volition exist interpreted on a Unix device differently:

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

This tin make iterating over each line problematic, and y'all may need to account for situations like this.

Graphic symbol Encodings

Another common problem that y'all may confront is the encoding of the byte data. An encoding is a translation from byte data to man readable characters. This is typically done by assigning a numerical value to correspond a character. The two most mutual encodings are the ASCII and UNICODE Formats. ASCII tin can only store 128 characters, while Unicode tin comprise up to 1,114,112 characters.

ASCII is actually a subset of Unicode (UTF-8), meaning that ASCII and Unicode share the aforementioned numerical to grapheme values. It's important to note that parsing a file with the incorrect graphic symbol encoding can lead to failures or misrepresentation of the character. For example, if a file was created using the UTF-8 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 y'all want to work with a file, the showtime thing to do is to open it. This is done by invoking the open() built-in function. open() has a single required statement that is the path to the file. open up() has a unmarried return, the file object:

                                            file                =                open                (                'dog_breeds.txt'                )                          

Later on you open up a file, the adjacent thing to learn is how to close it.

It'south important to call back that it'south your responsibility to shut the file. In near cases, upon termination of an application or script, a file volition be closed eventually. Nevertheless, there is no guarantee when exactly that will happen. This can lead to unwanted behavior including resources leaks. It'south also a best practice within Python (Pythonic) to brand sure that your code behaves in a manner that is well defined and reduces any unwanted behavior.

When you're manipulating a file, at that place are two means that yous can utilise to ensure that a file is closed properly, even when encountering an mistake. The first way to shut a file is to use the endeavour-finally cake:

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

If you're unfamiliar with what the try-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                :                # Further file processing goes hither                          

The with statement automatically takes intendance of closing the file in one case it leaves the with block, even in cases of error. I highly recommend that you use the with argument as much every bit possible, as it allows for cleaner code and makes handling any unexpected errors easier for you.

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

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

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

Character Meaning
'r' Open up for reading (default)
'w' Open for writing, truncating (overwriting) the file first
'rb' or 'wb' Open in binary way (read/write using byte data)

Let'due south go back and talk a little almost file objects. A file object is:

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

There are iii 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's a quick rundown of how everything lines upwards.

Text File Types

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

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

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

>>>

                                                  >>>                                    file                  =                  open                  (                  'dog_breeds.txt'                  )                  >>>                                    blazon                  (                  file                  )                  <class '_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 return either a BufferedReader or BufferedWriter file object:

>>>

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

Raw File Types

A raw file type is:

"by and large used as a low-level building-block for binary and text streams." (Source)

It is therefore non typically used.

Hither's an instance 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 up                  (                  'dog_breeds.txt'                  ,                  'rb'                  ,                  buffering                  =                  0                  )                  >>>                                    blazon                  (                  file                  )                  <class '_io.FileIO'>                              

Reading and Writing Opened Files

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

Method What It Does
.read(size=-1) This reads from the file based on the number of size bytes. If no argument is passed or None or -1 is passed, then the entire 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 then wraps back around. If no argument is passed or None or -i is passed, so the unabridged line (or residuum 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 yous used above, let's go through some examples of how to utilize these methods. Here'due south an instance of how to open and read the entire file using .read():

>>>

                                            >>>                                with                open                (                'dog_breeds.txt'                ,                'r'                )                equally                reader                :                >>>                                # Read & print the entire file                >>>                                print                (                reader                .                read                ())                Pug                Jack Russell Terrier                English Springer Spaniel                German Shepherd                Staffordshire Bull Terrier                Cavalier Male monarch Charles Spaniel                Aureate Retriever                West Highland White Terrier                Boxer                Border Terrier                          

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

>>>

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

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

>>>

                                            >>>                                f                =                open                (                'dog_breeds.txt'                )                >>>                                f                .                readlines                ()                # Returns a listing object                ['Pug\n', 'Jack Russell Terrier\north', 'English Springer Spaniel\northward', 'German language Shepherd\n', 'Staffordshire Balderdash Terrier\n', 'Cavalier Male monarch Charles Spaniel\n', 'Golden Retriever\n', 'West Highland White Terrier\due north', 'Boxer\northward', 'Border Terrier\n']                          

The above example can too be done by using list() to create a listing out of the file object:

>>>

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

Iterating Over Each Line in the File

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

>>>

                                                  >>>                                    with                  open                  (                  'dog_breeds.txt'                  ,                  'r'                  )                  equally                  reader                  :                  >>>                                    # Read and print the entire file line by line                  >>>                                    line                  =                  reader                  .                  readline                  ()                  >>>                                    while                  line                  !=                  ''                  :                  # The EOF char is an empty cord                  >>>                                    impress                  (                  line                  ,                  terminate                  =                  ''                  )                  >>>                                    line                  =                  reader                  .                  readline                  ()                  Pug                  Jack Russell Terrier                  English language Springer Spaniel                  German Shepherd                  Staffordshire Bull Terrier                  Condescending King Charles Spaniel                  Golden Retriever                  Westward Highland White Terrier                  Boxer                  Border Terrier                              

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

>>>

                                                  >>>                                    with                  open                  (                  'dog_breeds.txt'                  ,                  'r'                  )                  equally                  reader                  :                  >>>                                    for                  line                  in                  reader                  .                  readlines                  ():                  >>>                                    impress                  (                  line                  ,                  end                  =                  ''                  )                  Pug                  Jack Russell Terrier                  English Springer Spaniel                  German Shepherd                  Staffordshire Balderdash Terrier                  Cavalier King Charles Spaniel                  Aureate Retriever                  W Highland White Terrier                  Boxer                  Edge Terrier                              

Even so, the higher up examples can be farther simplified past iterating over the file object itself:

>>>

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

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

Now permit'south dive into writing files. Equally 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 detail. It's upwards to you to add the appropriate line ending(southward).

Here'due south a quick example of using .write() and .writelines():

                                                  with                  open                  (                  'dog_breeds.txt'                  ,                  'r'                  )                  equally                  reader                  :                  # Notation: readlines doesn't trim the line endings                  dog_breeds                  =                  reader                  .                  readlines                  ()                  with                  open                  (                  'dog_breeds_reversed.txt'                  ,                  'w'                  )                  as                  writer                  :                  # Alternatively y'all could use                  # writer.writelines(reversed(dog_breeds))                  # Write the dog breeds to the file in reversed order                  for                  brood                  in                  reversed                  (                  dog_breeds                  ):                  writer                  .                  write                  (                  breed                  )                              

Working With Bytes

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

>>>

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

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

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

You can really 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 similar this:

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

Sure plenty, when you open the file and read these bytes individually, yous 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                  (                  three                  ))                  >>>                                    print                  (                  byte_reader                  .                  read                  (                  two                  ))                  >>>                                    print                  (                  byte_reader                  .                  read                  (                  ane                  ))                  >>>                                    impress                  (                  byte_reader                  .                  read                  (                  ane                  ))                  b'\x89'                  b'PNG'                  b'\r\n'                  b'\x1a'                  b'\n'                              

A Full Case: dos2unix.py

Allow's bring this whole thing domicile 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\due north to \north.

This tool is broken upward into iii major sections. The first is str2unix(), which converts a cord from \r\n line endings to \n. The 2nd is dos2unix(), which converts a string that contains \r\n characters into \n. dos2unix() calls str2unix() internally. Finally, there's the __main__ block, which is called only when the file is executed as a script. Recollect of it as the main function plant in other programming languages.

                                                  """                  A simple script and library to convert files or strings from dos like                  line endings with Unix like line endings.                  """                  import                  argparse                  import                  os                  def                  str2unix                  (                  input_str                  :                  str                  )                  ->                  str                  :                  r                  """                                      Converts the string from \r\n line endings to \north                                      Parameters                                      ----------                                      input_str                                      The string whose line endings will be converted                                      Returns                                      -------                                      The converted cord                                      """                  r_str                  =                  input_str                  .                  replace                  (                  '                  \r\north                  '                  ,                  '                  \n                  '                  )                  return                  r_str                  def                  dos2unix                  (                  source_file                  :                  str                  ,                  dest_file                  :                  str                  ):                  """                                      Converts a file that contains Dos like line endings into Unix similar                                      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 together file being 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                  ,                  'w'                  )                  as                  writer                  :                  author                  .                  write                  (                  unix_content                  )                  if                  __name__                  ==                  "__main__"                  :                  # Create our Argument parser and gear up its description                  parser                  =                  argparse                  .                  ArgumentParser                  (                  description                  =                  "Script that converts a DOS like file to an Unix similar file"                  ,                  )                  # Add the arguments:                  #   - source_file: the source file nosotros want to convert                  #   - dest_file: the destination where the output should get                  # Note: the use of the argument blazon of argparse.FileType could                  # streamline some things                  parser                  .                  add_argument                  (                  'source_file'                  ,                  help                  =                  'The location of the source '                  )                  parser                  .                  add_argument                  (                  '--dest_file'                  ,                  aid                  =                  '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 assume we desire to                  # create a new file based on the quondam 1                  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 basics of reading and writing files, here are some tips and tricks to assistance you grow your skills.

__file__

The __file__ aspect is a special aspect of modules, similar to __name__. Information technology is:

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

Hither's a real world case. In one of my past jobs, I did multiple tests for a hardware device. Each test was written using a Python script with the test script file name used as a title. These scripts would then be executed and could print their status using the __file__ special attribute. Hither's an case folder structure:

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

Running main.py produces the post-obit:

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

Appending to a File

Sometimes, y'all may want to append to a file or start writing at the end of an already populated file. This is easily washed past using the 'a' grapheme for the mode statement:

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

When you examine dog_breeds.txt again, you'll see 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'                  )                  as                  reader                  :                  >>>                                    print                  (                  reader                  .                  read                  ())                  Pug                  Jack Russell Terrier                  English Springer Spaniel                  German Shepherd                  Staffordshire Bull Terrier                  Cavalier King Charles Spaniel                  Golden Retriever                  West Highland White Terrier                  Boxer                  Border Terrier                  Beagle                              

Working With Two Files at the Same Time

There are times when y'all may desire to read a file and write to another file at the same time. If you apply the example that was shown when you lot were learning how to write to a file, information technology can really 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                  ,                  'westward'                  )                  as                  writer                  :                  dog_breeds                  =                  reader                  .                  readlines                  ()                  author                  .                  writelines                  (                  reversed                  (                  dog_breeds                  ))                              

Creating Your Own Context Manager

In that location may come up a fourth dimension when y'all'll need finer control of the file object by placing it within a custom grade. When y'all do this, using the with statement tin no longer exist used unless you add a few magic methods: __enter__ and __exit__. By adding these, y'all'll accept created what's called a context managing director.

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

Here's a template that you tin can use to make your custom grade:

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

Now that y'all've got your custom form that is at present a context manager, you can use it similarly to the open up() congenital-in:

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

Here'due south a good example. Remember the beautiful Jack Russell image we had? Perhaps you want to open other .png files but don't want to parse the header file each time. Here's an case of how to practise this. This example also uses custom iterators. If yous're not familiar with them, bank check out Python Iterators:

                                                  class                  PngReader                  ():                  # Every .png file contains this in the header.  Use information technology to verify                  # the file is indeed a .png.                  _expected_magic                  =                  b                  '                  \x89                  PNG                  \r\northward\x1a\n                  '                  def                  __init__                  (                  cocky                  ,                  file_path                  ):                  # Ensure the file has the correct extension                  if                  non                  file_path                  .                  endswith                  (                  '.png'                  ):                  enhance                  NameError                  (                  "File must be a '.png' extension"                  )                  self                  .                  __path                  =                  file_path                  self                  .                  __file_object                  =                  None                  def                  __enter__                  (                  self                  ):                  self                  .                  __file_object                  =                  open                  (                  self                  .                  __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                  self                  def                  __exit__                  (                  self                  ,                  blazon                  ,                  val                  ,                  tb                  ):                  self                  .                  __file_object                  .                  close                  ()                  def                  __iter__                  (                  self                  ):                  # This and __next__() are used to create a custom iterator                  # Encounter https://dbader.org/weblog/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 nosotros                  # can't go any further and so stop the iteration past raising the                  # StopIteration.                  if                  self                  .                  __file_object                  is                  None                  or                  initial_data                  ==                  b                  ''                  :                  heighten                  StopIteration                  else                  :                  # Each chunk has a len, type, data (based on len) and crc                  # Catch these values and return them every bit a tuple                  chunk_len                  =                  int                  .                  from_bytes                  (                  initial_data                  ,                  byteorder                  =                  'big'                  )                  chunk_type                  =                  cocky                  .                  __file_object                  .                  read                  (                  4                  )                  chunk_data                  =                  cocky                  .                  __file_object                  .                  read                  (                  chunk_len                  )                  chunk_crc                  =                  self                  .                  __file_object                  .                  read                  (                  4                  )                  return                  chunk_len                  ,                  chunk_type                  ,                  chunk_data                  ,                  chunk_crc                              

Yous can now open .png files and properly parse them using your custom context director:

>>>

                                                  >>>                                    with                  PngReader                  (                  'jack_russell.png'                  )                  as                  reader                  :                  >>>                                    for                  l                  ,                  t                  ,                  d                  ,                  c                  in                  reader                  :                  >>>                                    print                  (                  f                  "                  {                  fifty                  :                  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\north'                  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 Snake

There are common situations that you may come across while working with files. Most 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 keen manufactures on how to handle these:

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

Additionally, there are born libraries out there that you lot can use to help you lot:

  • wave : 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 annal 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

In that location are plenty more out in that location. Additionally at that place are even 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

Yous're a File Wizard Harry!

Y'all did it! You lot now know how to work with files with Python, including some avant-garde techniques. Working with files in Python should now exist easier than e'er and is a rewarding feeling when you lot first 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 piece of work with common file types

If you have whatever questions, hit us upward in the comments.

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