Dragos Cazangiu
Dragos Cazangiu

Reputation: 157

Replacing lines in file based on dictionary

I have a csv file (Inventory.txt) containing information about multiple hosts.

host2,service2,10.172.23.2,255.255.255.0,test2
host3,service3,10.172.23.3,255.255.255.0,test3
host4,service4,10.172.23.4,255.255.255.0,test4
host5,service5,10.172.23.5,255.255.255.0,test5

I am extracting only the host name and ip from this file and building a dictionary:

my_dict={}
with open("Inventory.txt", 'r') as file:
    csvreader = csv.reader(file)
    for row in csvreader:
        my_dict[row[0]] = row[2]

I also have another file (changer.txt) that contains different parameters and some of them are the hosts from the inventory file, but with different ip's than in Inventory.txt:

cluster_info:
    esxi_name: "localhost.localdomain"
    esxi_datacenter: "Datacenter"
    esxi_datastore: "Datastore"
    host2: "10.172.23.10"
    host3: "10.76.23.56"
    packet_os_ipaddr: "10.164.243.118"

I am trying to replace the ip's in the changer.txt file with the ones from the dictionary by creating a temporary file, but it is quadrupling the lines and I am currently stuck. My full code below:

import csv

my_dict={}
with open("Inventory.txt", 'r') as file:
    csvreader = csv.reader(file)
    for row in csvreader:
        my_dict[row[0]] = row[2]
new_file = open('temporary.txt', 'w')
old_file = open('changer.txt','r')
lines = old_file.readlines()

for line in lines:
    for key in my_dict:
        new_file.write("\r"+key+": \""+my_dict[key]+"\"\n" if key in line else line)

Upvotes: 2

Views: 100

Answers (2)

hostingutilities.com
hostingutilities.com

Reputation: 9519

The problem is with the last three lines of code. Whenever I find myself wanting to perform actions in a for loop that is inside another for loop, I become a little suspicious of my own intentions. It could mean that there is code that needs to be split out from the for loop it is inside of. I will explain what I mean by that:

When the outer for loop runs, and gives us a line to work with, we need to take one of two actions. Either we write this line out unchanged, or we write it out with a new IP address from my_dict. We won't know which action we need to take until we've either

  • looped through the entire dictionary and did not find the key
  • or we found the key

That first bullet point requires us to loop through the entire dictionary. We cannot write to our file until we've finished this loop, so let's split up what we're doing into stuff that happens inside the loop, and stuff that happens after the inner loop is finished. While we're in the loop, we check for the conditions in those bullet points -- if we found the key or not -- and we will set a flag, I called the flag key_found in the code below, we set it to True if the key is found. Then, only after the loop is over (to prevent the line from being quadrupled), we check key_found to decide how we will to write to the file.

for line in lines:

    key_found = False
    for key in my_dict:
        if key in line:
            key_found = True
            break

    if key_found:
        new_file.write("\r"+key+": \""+my_dict[key]+"\"\n")
    else:
        new_file.write(line)

As an explanation for why your code was behaving the way it was behaving. Starting with the outer loop, you grab a line. Then for each of the four keys in my_dict you write out that line, perhaps modifying it when you do so, for each key in mydict = four different times! Moving the file writing out of the inner loop stops it from writing out each line multiple times.

This same type of scenario can happen whenever you have an item from one collection that you are trying to match up with an item in another collection of items.

Upvotes: 3

Arifa Chan
Arifa Chan

Reputation: 1017

Some workaround with hostingutilities-com great solution

import csv

my_dict = {row[0]: row[2] for row in csv.reader(open('inventory.txt'))}
new_file, old_file = open('temporary.txt', 'w'), open('changer.txt','r')
for line in old_file:
    exists = 0; host, ip = line.split(':')
    for k, v in my_dict.items():
        if k in host:
            ip = v; exists = 1
    new_file.write(host+": \""+ip+"\"\n") if exists else new_file.write(line)

Upvotes: 1

Related Questions