NickP
NickP

Reputation: 1414

Unexpected output from textfile - cleaning read in lines correctly

I am trying to use a very basic text file as a settings file. Three lines repeat in this order/format that govern some settings/input for my program. Text file is as follows:

Facebook
1#3#5#2
Header1#Header2#Header3#Header4
...

This is read in using the following Python code:

f = open('settings.txt', 'r')
for row in f:
    platform = f.readline()
    rows_to_keep = int(f.readline().split('#'))
    row_headers = f.readline().split('#')

    clean_output(rows_to_keep, row_headers, platform)

I would expect single string to be read in platform, an array of ints in the second and an array of strings in the third. These are then passed to the function and this is repeated numerous times.

However, the following three things are happening:

  1. Int doesn't convert and I get a TypeError
  2. First line in text file is ignored and I get rows to keep in platform
  3. \n at the end of each line

I suspect these are related and so am only posting one question.

Upvotes: 2

Views: 67

Answers (4)

user161778
user161778

Reputation: 534

With as few changes as possible, I've attempted to solve your issues and show you where you went wrong. @Daniel's answer is how I would personally solve the issues.

f = open('settings.txt', 'r')
#See 1. We remove the unnecessary for loop
platform = f.readline()
#See 4. We make sure there are no unwanted leading or trailing characters by stripping them out
rows_to_keep = f.readline().strip().split('#')
#See 3. The enumerate function creates a list of pairs [index, value]
for row in enumerate(rows_to_keep):
    rows_to_keep[row[0]] = int(row[1])
row_headers = f.readline().strip().split('#')
#See 2. We close the file when we're done reading
f.close()

clean_output(rows_to_keep, row_headers, platform)
  1. You don't need (and don't want) a for loop on f, as well as calls to readline. You should pick one or the other.
  2. You need to close f with f.close().
  3. You cannot convert a list to an int, you want to convert the elements in the list to int. This can be accomplished with a for loop.
  4. You probably want to call .strip to get rid of trailing newlines.

Upvotes: 0

Daniel
Daniel

Reputation: 563

Try this:

with open('settings.txt', 'r') as f:
    platform, rows_to_keep, row_headers = f.read().splitlines()
    rows_to_keep = [int(x) for x in rows_to_keep.split('#')]
    row_headers = row_headers.split('#')

    clean_output(rows_to_keep, row_headers, platform)

Upvotes: 1

stackunderflow
stackunderflow

Reputation: 202

There are several things going on here. First, when you do the split on the second line, you're trying to cast a list to type int. That won't work. You can, instead, use map.

rows_to_keep = map(int,f.readline().strip().split("#"))

Additionally, you see the strip() method above. That removes trailing whitespace chars from your line, ie: \n.

Try that change and also using strip() on each readline() call.

Upvotes: 0

radpotato
radpotato

Reputation: 1412

  1. You cannot call int on a list, you need do do some kind of list comprehension like

    rows_to_keep = [int(a) for a in f.readline().split('#')]

  2. You're reading a line, then reading another line from the file. You should either do some kind of slicing (see Python how to read N number of lines at a time) or call a function with the three lines after every third iteration.

  3. use .strip() to remove end of lines and other whitespace.

Upvotes: 1

Related Questions