Hal
Hal

Reputation: 372

Other options instead of using try-except

When line 2 in the text file has 'nope' then it will ignore the line and continue the next one. Is there another way to write this without using try and except? Can I use if else statement to do this?

Example of text file:

0 1 
0 2 nope
1 3 
2 5 nope

Code:

e = open('e.txt')
alist = []
for line in e:
    start = int(line.split()[0])
    target = int(line.split()[1])
    try:
        if line.split()[2] == 'nope':
            continue
    except IndexError:
        alist.append([start, target])

Upvotes: 9

Views: 7325

Answers (5)

Osman Mamun
Osman Mamun

Reputation: 2882

with open('e.txt', 'r') as f:
    alist = []
    for line in f:
        words = line.split()
        if len(words) > 2 and words[2] == 'nope':
            continue
        else:
            alist.append([int(words[0]), int(words[1])])

Upvotes: 3

ShinTakezou
ShinTakezou

Reputation: 9671

Can I use if else statement to do this?

You should use if-else statements, not exceptions, to control the flow in case of ordinary “events” which you expect. This is common “rule” in many languages, I think Python doesn't raise an exception here, Python is an exception here, but hopefully not in cases like this.

Following your code but without calling line.split() each time, removing the try-except and using a proper condition in the if:

alist = []
with open('e.txt') as e:
    for line in e:
        splitted = line.split()
        if len(splitted) > 2 and splitted[2] == 'nope':
            continue
        else:
            alist.append([int(splitted[0]), int(splitted[1])])

And of course you can negate the condition and avoid the continue:

if len(splitted) <= 2 or splitted[2] != 'nope':
    alist.append([int(splitted[0]), int(splitted[1])])

Which shows (another) weakness in case when you have less than 2 elements. Here you could use try: the exception in this case tells you that the input format is wrong (because you expect at least 2 elements, it seems), so you have to reject the input and warn the user. Also, you could intercept ValueError if those 2 elements aren't integers.

Moreover, if your input is allowed to contain extra spaces, you can use something like splitted[2].strip().


Readings on SO/SE about the try-except matter.

Upvotes: 1

Kasravnd
Kasravnd

Reputation: 107287

Yes, you can use str.endswith() method to check the trailing of the lines.

with  open('e.txt') as f:
    for line in f:
        if not line.endswith(('nope', 'nope\n')):
            start, target = line.split()
            alist.append([int(start), int(target)])

Note that when you use a with statement to open a file you don't need to close the file explicitly the file will be closed automatically at the end of the block.

Another but more optimized approach to solve this is to use a list comprehension in order to refuse appending to the list at each iteration and benefit from its performance compare to a regular loop.

with open('e.txt') as f:
    alist = [tuple(int(n) for i in line.split()) for line in f if not line.endswith(('nope', 'nope\n'))]

Note that still, since your code is exception prone because of converting strings to integer and splitting the lines, etc. It's better to use a try-except in order to prevent your code from possible exceptions and handle them properly.

with  open('e.txt') as f:
    for line in f:
        if not line.endswith(('nope', 'nope\n')):
            try:
                start, target = line.split()
            except ValueError:
                # the line.split() returns more or less than two items
                pass # or do smth else
            try:
                alist.append([int(start), int(target)])
            except ValueError:
                # invalid literal for int() with base 10
                pass # or do smth else

Another and yet Pythonic approach is to use csv module for reading the file. In that case you don't need to split the lines and/or use str.endswith().

import csv
with open("e.txt") as f:
    reader = csv.reader(f, delimiter=' ')
    alist = [(int(i), int(j)) for i, j, *rest in reader if not rest[0]]
    # rest[0] can be either an empty string or the word 'nope' if it's
    # an empty string we want the numbers. 

Upvotes: 6

Greg Eremeev
Greg Eremeev

Reputation: 1840

alist = []
with open('e.txt') as fin:
    for line in fin:
        rest_line, nope = line.strip().rsplit(' ', 1)
        if nope != 'nope':
            alist.append([int(rest_line), int(nope)])

Upvotes: 0

Druta Ruslan
Druta Ruslan

Reputation: 7412

If nope can be not only at the end of the line you can use this

with open('e.txt') as e:
    alist = [line.split() for line in e if 'nope' not in line]

print(alist)

Upvotes: 1

Related Questions