user1105224
user1105224

Reputation: 51

string formatting issue when using dictionary value

I have a weird problem when trying create a string when using a dictionary value. Basically, I have a function that opens a file, reads a line, and stores the values it finds in that line in a dictionary. Then, it sends those values to an external program. Here is the code:

def createLandscapes(file):

  landscapeParameters = {'FILE': "NULL",
                         'N': "NULL",
                         'K': "NULL",
                         'NUM': "100"}

  for line in file:
    if line == "END LANDSCAPES\n":
      break
    else:
      parameters = line.replace(" ", '').split(",")

      for parameter in parameters:
        parameter = parameter.split("=")
        if parameter[0] not in landscapeParameters:
          malformedFile()
        landscapeParameters[parameter[0]] = parameter[1]

      for key in landscapeParameters:
        if landscapeParameters[key] == "NULL":
          malformedFile()

      # This print statment is for diagnostic purposes
      print("./generateScoreTables {} {} {} {}".format(landscapeParameters['FILE'],
                                                       landscapeParameters['N'],
                                                       landscapeParameters['K'],
                                                       landscapeParameters['NUM']))

      os.system("./generateScoreTables {} {} {} {}".format(landscapeParameters['FILE'],
                                                           landscapeParameters['N'],
                                                           landscapeParameters['K'],
                                                           landscapeParameters['NUM']))

To make this very clear, the function looks for a series of parameter inputs on a single, comma separated line, in the form of

FILE=example, N=20, K=5, NUM=100

It takes those inputs and overrides the default inputs (if specified) in landscapeParameters, and uses the values in landscapeParameters to call an external program.

The strange this is that the string formatting doesn't seem to work correctly when I use the default parameters in landscapeParameters. What I mean by this is that if the function reads the line:

FILE=example, N=20, K=5, NUM=100

Everything works correctly, and the print statement prints:

./generateScoreTables example 20 5 100

However, if the function reads the line:

FILE=example, N=20, K=5

Where I've left NUM out to use the default parameter, I get the following output instead:

./generateScoreTables testland1 15
 0 100
Segmentation fault
sh: 2: 0: not found

It appears that format is not formatting this string correctly, but I don't understand why. Does anyone have any insight into this?

Upvotes: 1

Views: 204

Answers (2)

syntaxError
syntaxError

Reputation: 866

The problem has already been pointed out to you, but I'm still unable to comment so I'll leave this separate. This would involve reworking your code a little bit.

Once you get to this stage:

parameters = ['FILE=example', 'N=20', 'K=5', 'NUM=100']

# make a list of tuples with [(FILE, default), ('N', 20)...]
pars = [x.split("=") for x in parameters]

Now convert each twople into a Key, value pair in a dictionary dict_of_pars

dict_of_pars = {k: v for k, v in pars}
#dictionary with values for a single line
# {'FILE': 'example', 'N': '20', 'K': '5', 'NUM': '100'}

At this point you will have a dictionary containing all defined parameters for any particular line. If you make a function (that outputs) that holds default values you can send the available arguments for a line using **dict_of_pars in the call

# define output function with default parameters
def output(FILE='example, N='n', K='k', NUM='num'):
      os.system(FILE, N, K, NUM)

Now you can call the function using

  output(**dict_of_pars)  #will unpack the arguments into output function

Made one of these temporary dictionaries for each line in the file, pass it to the output. Hope this helps.

Upvotes: 2

Iain Dwyer
Iain Dwyer

Reputation: 184

You're updating the same variable on every loop, so if it reads one line that doesn't have a particular field it will use the value from the last time it read it.

Instead declare an empty dictionary inside the loop and use the .get function to have a default value if the key doesn't exist in the dictionary.

def createLandscapes(file):
    params = ['FILE','N','K','NUM']

    for line in file:
        if line == "END LANDSCAPES\n":
            break
        else:
            landscapeParameters = {}
            parameters = line.replace(" ", '').split(",")

            for parameter in parameters:
                parameter = parameter.split("=")
                if parameter[0] not in params:
                    malformedFile()
                landscapeParameters[parameter[0]] = parameter[1]

                for key in landscapeParameters:
                if landscapeParameters[key] == "NULL":
                    malformedFile()
         os.system("./generateScoreTables {} {} {} {}".format(landscapeParameters.get('FILE',''),
                                                           landscapeParameters.get('N',''),
                                                           landscapeParameters.get('K',''),
                                                           landscapeParameters.get('NUM',100)))

You'll probably need to tweak this a little bit, but it should give you more predictable results.

Upvotes: -1

Related Questions