Watch Now This tutorial has a related video class created by the Existent Python team. Watch information technology together with the written tutorial to deepen your agreement: Reading and Writing Files in Python

Ane of the most mutual tasks that y'all can exercise with Python is reading and writing files. Whether it's writing to a unproblematic 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 larn:

  • What makes up a file and why that's important in Python
  • The nuts 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 in that location are some tips in here that more advanced programmers may appreciate as well.

What Is a File?

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

At its core, a file is a contiguous gear up of bytes used to store information. This information is organized in a specific format and tin be anything as elementary as a text file or as complicated every bit a program executable. In the end, these byte files are then translated into binary one and 0 for easier processing by the computer.

Files on about modernistic file systems are equanimous of three chief parts:

  1. Header: metadata most the contents of the file (file name, size, type, then on)
  2. Data: contents of the file every bit written past the creator or editor
  3. Finish of file (EOF): special character 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 non thousands, of file extensions out there. For this tutorial, you lot'll simply 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 string that represents the location of a file. It'south broken up into three major parts:

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

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

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

Allow's say yous wanted to admission the cats.gif file, and your current location was in the same folder every bit path. In club to access the file, yous need to become through the path folder and so the to folder, finally arriving at the cats.gif file. The Binder Path is path/to/. The File Proper name is cats. The File Extension is .gif. So the full path is path/to/cats.gif.

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

Merely what about dog_breeds.txt? How would you access that without using the total path? You can utilize the special characters double-dot (..) to motility one directory up. This means that ../dog_breeds.txt will reference the dog_breeds.txt file from the directory of to:

                                / │ ├── path/  ← Referencing this parent folder |   │ |   ├── to/  ← 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 case, to access animals.csv from the to folder, you lot would use ../../animals.csv.

Line Endings

I 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 back 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.

Afterwards, this was standardized for teleprinters past 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\n). The ISO standard however allowed for either the CR+LF characters or just the LF character.

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

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

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

                                Pug\r \due north Jack Russell Terrier\r \northward English language Springer Spaniel\r \n High german Shepherd\r \n Staffordshire Bull Terrier\r \n Condescending Male monarch Charles Spaniel\r \n Gilded Retriever\r \north West Highland White Terrier\r \n Boxer\r \n Border Terrier\r \n                              

This can brand iterating over each line problematic, and yous may demand to account for situations like this.

Character Encodings

Another common problem that you lot may face is the encoding of the byte data. An encoding is a translation from byte data to homo readable characters. This is typically done by assigning a numerical value to represent a character. The two virtually common encodings are the ASCII and UNICODE Formats. ASCII can but store 128 characters, while Unicode tin can contain upwards to 1,114,112 characters.

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

Opening and Closing a File in Python

When yous want to work with a file, the showtime matter to do is to open it. This is done past invoking the open up() built-in function. open() has a unmarried required statement that is the path to the file. open up() has a single return, the file object:

                                            file                =                open up                (                'dog_breeds.txt'                )                          

After you open a file, the side by side thing to acquire is how to shut information technology.

It'south important to recall that it's your responsibility to shut the file. In most cases, upon termination of an application or script, a file volition be airtight eventually. However, there is no guarantee when exactly that will happen. This can pb to unwanted behavior including resource leaks. Information technology's also a best practice within Python (Pythonic) to make certain that your lawmaking behaves in a way that is well defined and reduces any unwanted beliefs.

When you lot're manipulating a file, there are two ways that y'all tin use to ensure that a file is closed properly, even when encountering an mistake. The first way to close a file is to use the effort-finally block:

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

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

The second way to shut a file is to utilize the with statement:

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

The with statement automatically takes care of endmost the file once it leaves the with block, even in cases of fault. I highly recommend that yous use the with statement equally much as possible, every bit information technology allows for cleaner lawmaking and makes treatment any unexpected errors easier for you.

Most likely, you'll also want to use the 2d positional argument, mode. This statement is a string that contains multiple characters to stand for how you want to open up the file. The default and most common 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 most commonly used ones are the post-obit:

Graphic symbol Meaning
'r' Open for reading (default)
'w' Open for writing, truncating (overwriting) the file start
'rb' or 'wb' Open in binary mode (read/write using byte information)

Let's go back and talk a little about file objects. A file object is:

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

There are 3 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 upwardly.

Text File Types

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

                                                  open up                  (                  'abc.txt'                  )                  open up                  (                  'abc.txt'                  ,                  'r'                  )                  open up                  (                  'abc.txt'                  ,                  'due west'                  )                              

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

>>>

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

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

Buffered Binary File Types

A buffered binary file blazon is used for reading and writing binary files. Hither 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 up                  (                  'dog_breeds.txt'                  ,                  'rb'                  )                  >>>                                    type                  (                  file                  )                  <class '_io.BufferedReader'>                  >>>                                    file                  =                  open                  (                  'dog_breeds.txt'                  ,                  'wb'                  )                  >>>                                    blazon                  (                  file                  )                  <grade '_io.BufferedWriter'>                              

Raw File Types

A raw file blazon is:

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

It is therefore non typically used.

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

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

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

>>>

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

Reading and Writing Opened Files

Once yous've opened up a file, you'll desire to read or write to the file. First off, allow's cover reading a file. There are multiple methods that can be chosen on a file object to aid 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, then the entire file is read.
.readline(size=-1) This reads at most size number of characters from the line. This continues to the end of the line and then wraps back effectually. If no statement is passed or None or -1 is passed, then the entire line (or rest of the line) is read.
.readlines() This reads the remaining lines from the file object and returns them every bit a list.

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

>>>

                                            >>>                                with                open                (                'dog_breeds.txt'                ,                'r'                )                as                reader                :                >>>                                # Read & impress the entire file                >>>                                print                (                reader                .                read                ())                Pug                Jack Russell Terrier                English language Springer Spaniel                German Shepherd                Staffordshire Balderdash Terrier                Cavalier King Charles Spaniel                Golden Retriever                Due west Highland White Terrier                Boxer                Border Terrier                          

Here's an case 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 first 5 characters of the line 5 times                >>>                                impress                (                reader                .                readline                (                5                ))                >>>                                # Notice that line is greater than the 5 chars and continues                >>>                                # down the line, reading 5 chars each time until the end of the                >>>                                # line and and then "wraps" around                >>>                                print                (                reader                .                readline                (                v                ))                >>>                                print                (                reader                .                readline                (                5                ))                >>>                                print                (                reader                .                readline                (                v                ))                >>>                                impress                (                reader                .                readline                (                5                ))                Pug                Jack                Russe                ll Te                rrier                          

Here's an case of how to read the unabridged file equally a listing using the Python .readlines() method:

>>>

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

The above case can also be done by using listing() to create a listing out of the file object:

>>>

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

Iterating Over Each Line in the File

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

>>>

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

Another way y'all could iterate over each line in the file is to employ 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'                  )                  as                  reader                  :                  >>>                                    for                  line                  in                  reader                  .                  readlines                  ():                  >>>                                    impress                  (                  line                  ,                  end                  =                  ''                  )                  Pug                  Jack Russell Terrier                  English Springer Spaniel                  German Shepherd                  Staffordshire Bull Terrier                  Cavalier King Charles Spaniel                  Golden Retriever                  West Highland White Terrier                  Boxer                  Edge Terrier                              

However, the above examples can be further simplified by iterating over the file object itself:

>>>

                                                  >>>                                    with                  open up                  (                  'dog_breeds.txt'                  ,                  'r'                  )                  as                  reader                  :                  >>>                                    # Read and impress the entire file line past line                  >>>                                    for                  line                  in                  reader                  :                  >>>                                    impress                  (                  line                  ,                  end                  =                  ''                  )                  Pug                  Jack Russell Terrier                  English Springer Spaniel                  High german Shepherd                  Staffordshire Bull Terrier                  Cavalier King Charles Spaniel                  Golden Retriever                  West Highland White Terrier                  Boxer                  Border Terrier                              

This concluding approach is more Pythonic and tin can be quicker and more memory efficient. Therefore, it is suggested you use this instead.

Now let's 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 item. It's upwardly to y'all to add together the appropriate line catastrophe(southward).

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

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

Working With Bytes

Sometimes, you may need to work with files using byte strings. This is done by adding the 'b' graphic symbol to the style argument. All of the same methods for the file object apply. Even so, each of the methods look and return a bytes object instead:

>>>

                                                  >>>                                    with                  open                  (                  'dog_breeds.txt'                  ,                  'rb'                  )                  every bit                  reader                  :                  >>>                                    impress                  (                  reader                  .                  readline                  ())                  b'Pug\north'                              

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

A cute picture of a Jack Russell Terrier
Image: CC By iii.0 (https://creativecommons.org/licenses/past/three.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 eight bytes broken upwards similar this:

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

Sure enough, when you open the file and read these bytes individually, you tin can come across that this is indeed a .png header file:

>>>

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

A Full Example: dos2unix.py

Allow'due south bring this whole affair home and look at a full case of how to read and write to a file. The post-obit is a dos2unix like tool that volition convert a file that contains line endings of \r\n to \n.

This tool is broken upwards into iii major sections. The first is str2unix(), which converts a string from \r\north line endings to \north. The second is dos2unix(), which converts a string that contains \r\due north characters into \northward. dos2unix() calls str2unix() internally. Finally, at that place'southward the __main__ block, which is called only when the file is executed as a script. Think of it as the master role constitute in other programming languages.

                                                  """                  A uncomplicated script and library to catechumen files or strings from dos like                  line endings with Unix like line endings.                  """                  import                  argparse                  import                  bone                  def                  str2unix                  (                  input_str                  :                  str                  )                  ->                  str                  :                  r                  """                                      Converts the string from \r\n line endings to \n                                      Parameters                                      ----------                                      input_str                                      The string whose line endings will be converted                                      Returns                                      -------                                      The converted string                                      """                  r_str                  =                  input_str                  .                  replace                  (                  '                  \r\n                  '                  ,                  '                  \northward                  '                  )                  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'                  )                  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 fix 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 we want to catechumen                  #   - dest_file: the destination where the output should become                  # Note: the use of the statement type of argparse.FileType could                  # streamline some things                  parser                  .                  add_argument                  (                  'source_file'                  ,                  help                  =                  'The location of the source '                  )                  parser                  .                  add_argument                  (                  '--dest_file'                  ,                  help                  =                  'Location of dest file (default: source_file appended with `_unix`'                  ,                  default                  =                  None                  )                  # Parse the args (argparse automatically grabs the values from                  # sys.argv)                  args                  =                  parser                  .                  parse_args                  ()                  s_file                  =                  args                  .                  source_file                  d_file                  =                  args                  .                  dest_file                  # If the destination file wasn't passed, then presume we want to                  # create a new file based on the erstwhile one                  if                  d_file                  is                  None                  :                  file_path                  ,                  file_extension                  =                  os                  .                  path                  .                  splitext                  (                  s_file                  )                  d_file                  =                  f                  '                  {                  file_path                  }                  _unix                  {                  file_extension                  }                  '                  dos2unix                  (                  s_file                  ,                  d_file                  )                              

Tips and Tricks

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

__file__

The __file__ attribute is a special aspect of modules, similar 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 globe example. In one of my past jobs, I did multiple tests for a hardware device. Each exam was written using a Python script with the test script file proper noun used every bit a championship. These scripts would then be executed and could print their status using the __file__ special attribute. Here's an example folder structure:

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

Running principal.py produces the following:

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

I was able to run and get the status of all my tests dynamically through use of the __file__ special attribute.

Appending to a File

Sometimes, y'all may desire to append to a file or starting time writing at the end of an already populated file. This is hands done by using the 'a' grapheme for the style statement:

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

When you examine dog_breeds.txt once 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                  :                  >>>                                    impress                  (                  reader                  .                  read                  ())                  Pug                  Jack Russell Terrier                  English Springer Spaniel                  German Shepherd                  Staffordshire Bull Terrier                  Condescending King Charles Spaniel                  Aureate Retriever                  Westward Highland White Terrier                  Boxer                  Border Terrier                  Beagle                              

Working With Ii Files at the Same Time

At that place are times when you lot may want to read a file and write to another file at the same time. If you apply the example that was shown when you were learning how to write to a file, it tin actually exist combined into the following:

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

Creating Your Own Context Director

There may come a time when you lot'll demand finer command of the file object past placing information technology inside a custom form. When you do this, using the with statement can no longer exist used unless you add a few magic methods: __enter__ and __exit__. By adding these, you'll take created what's chosen a context manager.

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

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

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

Now that you've got your custom form that is now a context manager, you can use information technology similarly to the open() congenital-in:

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

Hither'due south a skilful case. Call up the cute Jack Russell image we had? Perhaps you desire to open other .png files just don't want to parse the header file each fourth dimension. Here's an example of how to do this. This example also 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 information technology to verify                  # the file is indeed a .png.                  _expected_magic                  =                  b                  '                  \x89                  PNG                  \r\due north\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 up                  (                  self                  .                  __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__                  (                  self                  ,                  blazon                  ,                  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__                  (                  cocky                  ):                  # 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                  (                  iv                  )                  # The file hasn't been opened or reached EOF.  This means we                  # can't go any further so end the iteration by 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 render them as a tuple                  chunk_len                  =                  int                  .                  from_bytes                  (                  initial_data                  ,                  byteorder                  =                  'big'                  )                  chunk_type                  =                  self                  .                  __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 manager:

>>>

                                                  >>>                                    with                  PngReader                  (                  'jack_russell.png'                  )                  every bit                  reader                  :                  >>>                                    for                  50                  ,                  t                  ,                  d                  ,                  c                  in                  reader                  :                  >>>                                    print                  (                  f                  "                  {                  fifty                  :                  05                  }                  ,                                    {                  t                  }                  ,                                    {                  c                  }                  "                  )                  00013, b'IHDR', b'five\x121k'                  00001, b'sRGB', b'\xae\xce\x1c\xe9'                  00009, b'pHYs', b'(<]\x19'                  00345, b'iTXt', b"50\xc2'Y"                  16384, b'IDAT', b'i\x99\x0c('                  16384, b'IDAT', b'\xb3\xfa\x9a$'                  16384, b'IDAT', b'\xff\xbf\xd1\n'                  16384, b'IDAT', b'\xc3\x9c\xb1}'                  16384, b'IDAT', b'\xe3\x02\xba\x91'                  16384, b'IDAT', b'\xa0\xa99='                  16384, b'IDAT', b'\xf4\x8b.\x92'                  16384, b'IDAT', b'\x17i\xfc\xde'                  16384, b'IDAT', b'\x8fb\x0e\xe4'                  16384, b'IDAT', b')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 y'all may come across while working with files. Well-nigh of these cases can exist handled using other modules. Two mutual 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, there are built-in libraries out there that you can utilise to assistance you lot:

  • wave : read and write WAV files (audio)
  • aifc : read and write AIFF and AIFC files (audio)
  • sunau : read and write Dominicus AU files
  • tarfile : read and write tar archive files
  • zipfile : work with Nix archives
  • configparser : hands 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 10 .plist files

In that location are plenty more out at that place. Additionally there 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 : prototype reading and manipulation

You're a File Wizard Harry!

You did information technology! Y'all now know how to 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 advanced techniques when working with files
  • Some libraries to work with common file types

If you lot accept any questions, striking u.s.a. up in the comments.

Sentry At present This tutorial has a related video class created past the Existent Python team. Watch it together with the written tutorial to deepen your understanding: Reading and Writing Files in Python