Tuesday, August 15, 2017

Exploring the fileinput module in Python : change file contents in place and more

FileInput : 

I was in need of modifying the contents of a file in place and i was looking at what my options were.
Quick google search finally helped me land on fileinput and i am really glad , how wonderful it is to use this module for the same purpose and it obviously does more than that.

Contents of the Fastfile looked like below and we wanted to change the version number as part of the automation.
Just ignore the regex i used .. I am anyways not really good at it :-)



import fileinput
import re


def modify_fastfile(full_path, version):
    print(full_path)
    mod_ver = r'  version_number = "{}"'.format(version)
    print(mod_ver)
    pattern = r'\s\sversion_number = \"\d.*\"'
    with fileinput.FileInput(full_path, inplace=True, backup='.bak') as file:
        for line in file:
            line = re.sub(pattern, mod_ver, line.rstrip())
            print(line)
    

But the things to focus really on are the parameters.
  • inplace = True 
  • backup = '.bak'
And thats it voila we were able to change the contents of the file in place.

You should really go over quickly the documentation on https://docs.python.org/2/library/fileinput.html 

This module implements a helper class and functions to quickly write a loop over standard input or a list of files. If you just want to read or write one file see open().

I am showing couple of ways in which it can be used.

  • In first case we are just accepting the input from standard input 
  • In second case we are providing list of files 

#! /usr/bin/env python3
import fileinput

with fileinput.input() as f:
    for line in f:
        print(line, end='')

# ls | ./file_input.py
# __pycache__
# file_input.py
# file_input_multi_files.py
#! /usr/bin/env python3
import fileinput

with fileinput.input(files=('file_input.py', 'file_input_multi_files.py')) as f:
    for line in f:
        print(f.filename(), f.lineno(), line, end='')


# ./file_input_multi_files.py

# file_input.py 1 #! /usr/bin/env python3
# file_input.py 2 import fileinput
# file_input.py 3
# file_input.py 4 with fileinput.input() as f:
# file_input.py 5     print()
# file_input.py 6     for line in f:
# file_input.py 7         print(line, end='\n')file_input_multi_files.py 8 #! /usr/bin/env python3
# file_input_multi_files.py 9 import fileinput
# file_input_multi_files.py 10
# file_input_multi_files.py 11 with fileinput.input(files=('file_input.py', 'file_input_multi_files.py')) as f:
# file_input_multi_files.py 12     for line in f:
# file_input_multi_files.py 13         print(f.filename(), f.lineno(), line, end='')%

Now when i had a look at the definition in the docs , i saw openhooks parameter.
Basically this allows us to have compressed and uncompressed files in the list. Thats a great flexibility.

I was thinking of problem that David solved using generators and thought  fileinput can also be used to solve the same problem.

If you have seen http://www.dabeaz.com/generators-uk/GeneratorsUK.pdf from @dabeaz ,  which i think you should absolutely go through cause he is just an amazing Python Instructor.




Well thats it folks i hope you like this post and you explore the  fileinput module further and share your findings with the community.


No comments:

Post a Comment