0

I'm supposed to code for a program that continuously asks a users for a file name until it enters the correct one. Then the find_min_percent is supposed to take one argument, one line (str) from the GDP.txt file then iterate through the line to find the smallest value and return that value. Here's my code so far

line = " " 

def open_file(): 
    ''' Repeatedly prompt until a valid file name allows the file to be opened.'''
    while True: 
        user_input = input('Enter a file name: ')
        try: 
            file = open(user_input, 'r')
            return file 
            break
        except FileNotFoundError: 
            print('Error. Please try again') 
            open_file()

def find_min_percent(line): 
    '''Find the min percent change in the line; return the value and the index.'''
    percent_lst = []
    line = file.readline(9)
    percent_lst += [line]
    percent_int = [float(i) for i in percent_lst]
    min_value = 10000
    for percent in percent_int:
        if percent < min_value:
            min_value = percent
            return min_value 


print(open_file())
print (find_min_percent(line))

My problem is with the readline(). It says that the variable file is undefined. The outline of this code does not include file in the "def find_min_percent(line):" part. So I don't know how I would go about fixing this. I also can't set line outside of the function because I have to use the same line variable for other functions later in the program to read other lines. So I don't know what to do so that it doesn't keep

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
Nora
  • 15
  • 1
  • 2
  • 7
  • 1
    Why aren't you saving the return value of `open_file()` and passing it into `find_min_percent`? `print(open_file())` calls `open_file()`, prints the representation of the returned file object, and then throws it away. – PM 2Ring May 31 '17 at 16:15
  • 1
    Oups! Recursing from an error handler is a **very** bad idea... Please remove the `break` line from `open_file` (useless after a `return`), and remove the awful `open_file` line from the end of the function. – Serge Ballesta May 31 '17 at 16:19

3 Answers3

2

A variable you define in one function can't be accessed from the other one. To fix that, you could for example, do this (store the returned value in a "main function" variable and pass it to your next function):

def find_min_percent(line): 
    '''Find the min percent change in the line; return the value and the index.'''
    percent_lst = []
    # You can use f from this function, as long as you don't modify it
    line = f.readline(9)
    percent_lst += [line]
    percent_int = [float(i) for i in percent_lst]
    min_value = 10000
    for percent in percent_int:
        if percent < min_value:
            min_value = percent
            return min_value 


f = open_file()
print(f)
print (find_min_percent(line))

By the way, the way you use your line variable is weird. It's only used inside find_min_percent but defined outside of the function and even passed as a parameter. Why? What are you trying to achieve?

(see here for a post about accessing variables defined outside a function)

Thomas Kowalski
  • 1,995
  • 4
  • 20
  • 42
  • Like I said at the end of the post, the actual program I am supposed to write is much longer than this. I am writing the code piece by piece and this is as far as I have gotten so far. The reason I have it defined outside of the function is because later I will need to have a find_max_percent and find_gdp that takes the line string. – Nora May 31 '17 at 16:19
  • 1
    This doesn't have to be a problem. You can have a "global" variable `f` or `file` that you can access everywhere in your module (as long as it's defined outside of a function). I'll edit my answer so you can see. – Thomas Kowalski May 31 '17 at 16:21
  • @NouraAsrar: if you want 2 functions to share a variable, the best way is to pass a parameter like Thomas as shown here. An alternative way that should be used only in special use cases is to have a global variable. But if you fail to declare it as global in your functions, `file` in `open_file` will be a local variable hiding the global one! If you do not understand this sentence keep away from global variables... – Serge Ballesta May 31 '17 at 16:23
  • 1
    On another unrelated point, I kind of worry about the fact I don't see a file closing anywhere. You should always close a file after having worked with it. Here, you can add `f.close()` at the end. – Thomas Kowalski May 31 '17 at 16:23
0

The returned file variable is out of the scope of the function Fixed code:

line = " " 

def open_file(): 
    ''' Repeatedly prompt until a valid file name allows the file to be opened.'''
    while True: 
        user_input = input('Enter a file name: ')
        try: 
            file = open(user_input, 'r')
            return file 
            break
        except FileNotFoundError: 
            print('Error. Please try again') 
            open_file()

def find_min_percent(line,file): 
    '''Find the min percent change in the line; return the value and the index.'''
    percent_lst = []
    line = file.readline(9)
    percent_lst += [line]
    percent_int = [float(i) for i in percent_lst]
    min_value = 10000
    for percent in percent_int:
        if percent < min_value:
            min_value = percent
            return min_value 

temp=open_file()
print(temp)
print (find_min_percent(line,temp))
Vijayabhaskar J
  • 417
  • 2
  • 4
  • 17
0

Another way of doing this:

def open_file(): 
    ''' Repeatedly prompt until a valid file name allows the file to be opened.'''
    while True: 
        user_input = input('Enter a file name: ')
        try: 
            file = open(user_input, 'r')
            print('user_input: ', user_input)
            line = file.readline(9)
            file.close()
            return find_min_percent(line)
        except FileNotFoundError: 
            print('Error. Please try again') 
            open_file()

def find_min_percent(line): 
    '''Find the min percent change in the line; return the value and the index.'''
    percent_lst = []
#    line = file.readline(9)
    percent_lst += [line]
    percent_int = [float(i) for i in percent_lst]
    min_value = 10000
    for percent in percent_int:
        if percent < min_value:
            min_value = percent
            return min_value 


print(open_file())

Note that I am not sure about the correctness of your find_min_percent method. Also if you manually open file (without using with open) you need to explicitly close as well.

Nurjan
  • 5,889
  • 5
  • 34
  • 54