简体   繁体   中英

Trouble iterating through lines in a file in Python

I have a class that simulates a scenario for calculating paths in a network using the distance vector routing algorithm. The class has an attribute, map_file, which is the name of a file that describes the connections in the network. Here is a snippet of code from the DVSimulator class:

def populate_map(self):
    with open(self.map_file,'r') as f:
        for line in f:
            data = line.split()
            length_of_link = data[2]
            ...

There is a file called "test_map1". It looks like this:

A  B  2.1
B  C  1.2
A  C  1.0
C  D  1.5   

Every line in the file indicates a connection between two nodes. Here, Node A is connected to Node B with a distance of 2.1, Node B to Node C with a distance of 1.2, etc.

Here is the setUp() method from my pyunit TestDVSimulator class:

def setUp(self):
     self.split_horizon_simulator1 = dv_simulator.DVSimulator("test_map1",True)
     self.no_split_simulator1 = dv_simulator.DVSimulator("test_map1", False)
     self.split_horizon_simulator2 = dv_simulator.DVSimulator("test_map2",True)
     self.no_split_simulator2 = dv_simulator.DVSimulator("test_map2",True)

Here is a snippet of code from the test_populate_map() method in the TestDVSimulator class:

 def test_populate_map(self):
     """Tests the populate_map() method in DVSimulator"""
     splitty1 = self.split_horizon_simulator1
     no_splitty1 = self.no_split_simulator1
     splitty2 = self.split_horizon_simulator2
     no_splitty2 = self.no_split_simulator2
     splitty1.populate_map()
     no_splitty1.populate_map()
     splitty2.populate_map()
     splitty2.populate_map()
     ...

Now, when I try to unittest the populate_map() method using the map_file shown above I get the following error message:

ERROR: Tests the populate_map() method in DVSimulator
----------------------------------------------------------------------
Traceback (most recent call last):
  File "dv_simulator_test.py", line 28, in test_populate_map
    splitty1.populate_map()
  File "/home/grads/klepp/6760/DistanceVectorProject/dv_simulator.py", line 33, in populate_map
    length_of_link = data[2]
IndexError: list index out of range

However, I know that each line in the file has length 3, and so data[2] is most definitely not out of range. Interestingly, if edit the populate_map() method as follows:

 def populate_map(self):
     with open(self.map_file,'r') as f:
         for line in f.readlines():            
             print "line from map file: " + line
             data = line.split()
             print "data: " + str(data)
             print str(data[0])
             print str(data[1])
             print str(data[2])
             length_of_link = data[2]
             ...

the output looks like this:

line from map file: A B 2.1

data: ['A', 'B', '2.1']
A
B
2.1
line from map file: B C 1.2

data: ['B', 'C', '1.2']
B
C 
1.2
line from map file: A C 1.0

data: ['A', 'C', '1.0']
A
C
1.0
line from map file: C D 1.5

data: ['C', 'D', '1.5']
C
D
1.5
line from map file: 

data: []
EF
======================================================================
ERROR: Tests the populate_map() method in DVSimulator
----------------------------------------------------------------------
Traceback (most recent call last):
  File "dv_simulator_test.py", line 28, in test_populate_map
    splitty1.populate_map()
  File "/home/grads/klepp/6760/DistanceVectorProject/dv_simulator.py", line 30, in populate_map
    print str(data[0])
IndexError: list index out of range

That is to say, that str(data[0]) clearly prints out some value, in fact it prints it out four times in a row, but then it says that data[0] is out of range nonetheless. For some reason the code seems to be iterating through the lines in the file and calling line.split() on each line before it runs the line of code for length_of_link = data[2].

Does anyone know what is going wrong and how I can fix this?

Here is the full script of the populate_map() method in the DVSimulator class:

#The DVSimulator class simulates a Distance Vector Routing scenario                                                                                        
import routingtable
import dv_router

class DVSimulator:

  def __init__(self, map_file, split_horizon,verbosity = False, test_destination=''):

     self.routers_dictionary = {}
     self.neighbors_dictionary  = {} #a dictionary of router:dict pairs where dict is a dictionary of router values keyed by their names                
     self.breakables = [] #string tuples of (router1, router2) signifying a link to break upon convergence                                              
     self.using_split_horizon = split_horizon
     self.map_file = map_file
     self.verbose = verbosity
     self.number_of_iterations = 0
     self.test_dest = test_destination

 def populate_map(self):

     with open(self.map_file,'r') as f:
         for line in f:

             print "line from map file: " + line
             data = line.split()
             print "data: " + str(data)
             print str(data[0])
             print str(data[1])
             print str(data[2])
             length_of_link = data[2]
             if len(data) == 4:
                 breakables.append((data[0],data[1]))
             router1 = data[0]
             router2 = data[1]
             neighbor_pair = [router1, router2]

             for each in neighbor_pair:
                 if each == router1:
                     other = router2
                 else:
                     other = router1
                 if each not in self.routers_dictionary:
                     self.routers_dictionary[each] = dv_router.DVRouter(each, self.using_split_horizon)
                     self.neighbors_dictionary[each] = {}
                     for router in self.routers_dictionary:
                         if router != other:
                             self.routers_dictionary[router].add_link(each)
                     self.routers_dictionary[each].routing_table.edit_distance_to(each, 0, each)
              for each in neighbor_pair:
                  if each == router1:
                      other = router2
                  else:
                      other = router1
                  self.routers_dictionary[each].add_link(other,length_of_link)
                  self.neighbors_dictionary[each][other] = self.routers_dictionary[other]

The error lies in the test_map1 file. At the end of the file is a blank line. If the line is removed, the code runs as expected. An if statement, as suggested, could also be added to branch correctly for blank lines.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM