-1

So I previously had my code set-up to access a list that was declared outside functions making it a global variable, for the task I was assigned the lecturer is insisting that we do not use global variables. So now I have the following code which obviously gives a "data_set undefined error"

The idea being that I create a list from a csv file and then pass that list to several other functions so that I can get elements from the data_set list and create new outputs.

import csv
import sys

def print_menu():
    print("ACME WEATHER DATA APP")
    print("1) Choose weather data file")
    print("2) See data for selected day")
    print("3) Calculate average statistics for the data")
    print("4) Print a scatterplot of the average temperatures")
    print("0) Quit program")

def loadFile(x):
    data_set = []
    data_set.clear()
    with open(x, "r") as readfile:
        csv_reader = csv.reader(readfile, delimiter= ';')
        for row in csv_reader:
            data_set.append(row)
    print("Loaded weather data from", (x[0:-4]).capitalize())
    print()
    return data_set    

def avgDay(x, data_set):
    for line in data_set:
        if(len(x) == 5 and (x[3:5] + "-" + x[0:2]) in line[0]):
           print("The weather on", x, "was on average", line[2], "centigrade")


def lowHigh(x, data_set):
    for line in data_set:
        if(len(x) == 5 and (x[3:5] + "-" + x[0:2]) in line[0]):
            print("The lowest temperature was", line[3], "and the highest temperature was", line[4])


def rain(x, data_set):
    for line in data_set:
        if(len(x) == 5 and (x[3:5] + "-" + x[0:2]) in line[0]):
            print("There was", line[1],"mm rain")
            print()

def avgMonth(data_set):
    avgList= []
    for line in data[1:]:
        avgList.append(line[2])
    avgList= [float(i) for i in avgList]
    avg = sum(avgList)/len(avgList)
    print("The average temperature for the 25 day period was", round(avg,1))


def avgLow(data_set):
    avgList= []
    for line in data[1:]:
        avgList.append(line[3]) 
    avgList= [float(i) for i in avgList]
    avg = sum(avgList)/len(avgList)
    print("The average lowest temperature was", round(avg,1))


def avgHigh(data_set):
    avgList= []
    for line in data[1:]:
        avgList.append(line[4])  
    avgList= [float(i) for i in avgList]
    avg = sum(avgList)/len(avgList)

    print("The average highest temperature was", round(avg,1))
    print()

def print_tempLine(day, month, temp):
    print(day + "." + month + " ", end="")
    print("   "*(temp+5) + "-", end="")
    print()


def print_tempAxis():
    print("      ", end="")
    for i in range(-5,16):
        print("{:02d} ".format(i), end="")
    print()

def scatPlot(data_set):
    for line in data[1:]:
            day_month=line[0].split("-")
            temp=int(round(float(line[2]),0))
            print_tempLine(day_month[2],day_month[1],temp)
            print_tempAxis()
            print()

def menu_number():
    number = int(input("Choose what to do: "))
    if (number) == 1:
        x = input("Give name of the file: " )
        loadFile(x)
        print_menu()
        menu_number()

    elif (number) == 2:
        x = input("Give a date (dd.mm): ")
        avgDay(x, data_set)
        lowHigh(x, data_set)
        rain(x, data_set)
        print_menu()
        menu_number()

    elif (number) == 3:
        avgMonth(data_set)
        avgLow(data_set)
        avgHigh(data_set)
        print_menu()
        menu_number()

    elif (number) == 4:
        scatPlot(data_set)
        print_menu()
        menu_number()

    elif (number) == 0:
        sys.exit()

    else:
        print("\n Your selection is invalid, please try again!\n")
        print_menu()
        menu_number()

print_menu()
menu_number()

I understand that when I return data_set in my loadFile(x) that it needs to be assigned to a variable somehow so that it can be accessed outside the local scope, I just am not sure how that is done. I have tried changing loadFile(x) to data_set = loadFile(x) within menu_number function, this just resulted in it giving the following error "local variable 'data_set' referenced before assignment". So is there something I have missed or do I need to re-write the code somehow?

Edit: Sorry did not realize I needed to provide full stack trace error

Traceback (most recent call last):
  File "C:\Users\alexa\Documents\XAMK\python scripts\test.py", line 126, in <module>
    menu_number()
  File "C:\Users\alexa\Documents\XAMK\python scripts\test.py", line 95, in menu_number
    menu_number()
  File "C:\Users\alexa\Documents\XAMK\python scripts\test.py", line 99, in menu_number
    avgDay(x, data_set)
NameError: name 'data_set' is not defined

Edit 2: csv sample code

"DateTime";"Precipitation";"Mean temperature";"Minimum temperature";"Maximum temperature";"Typical maximum temperature";"Typical maximum temperature";"Typical minimum temperature";"Typical minimum temperature";"Fairly typical maximum temperature";"Fairly typical maximum temperature";"Fairly typical minimum temperature";"Fairly typical minimum temperature"
"2019-10-06";0;4;0.4;6.8;10.3;11.9;4.5;7.2;7.6;13.8;0.9;9.8
"2019-10-07";0.1;4.4;2.6;7.8;10.1;11.8;4.4;7;7.4;13.6;0.8;9.7
"2019-10-08";0;4.9;2.3;7.2;10;11.6;4.2;6.9;7.2;13.4;0.6;9.5
"2019-10-09";1.1;4.8;1.8;7.6;9.8;11.4;4.1;6.7;6.9;13.3;0.5;9.4
2
  • 2
    Post the full error message, including the stack trace. You really need to be providing a minimal reproducible example, not just dumping your whole code here. Commented May 15, 2020 at 21:58
  • Functions return values, not names. If you want to use the value that was returned, you need to... use it, for example by storing it somewhere. Writing add(1, 2) (supposing that you implemented such a function) is the same as if you wrote 1 + 2 - the 3 result doesn't do anything by itself (and it doesn't matter what name, if any, the add function uses internally for that result). Commented May 15, 2020 at 22:14

2 Answers 2

0

It would be helpful if you can provide an example csv file so that I can test the workflow. But it looks like the problem is that you call loadFile(x), and it has a return statement, but nothing is set to that return statement. So you are on the right track with data_set = loadFile(x). The problem is, when you call the menu_number function again, variable values are not preserved. So on that second call, data_set lost its meaning.

You can fix this by passing the value of data_set to the function, so your menu_number would look more like

def menu_number(data_set=None):
    number = int(input("Choose what to do: "))
    if (number) == 1:
        x = input("Give name of the file: " )
        data_set=loadFile(x)
        print_menu()
        # passing data_set value along
        # with the call
        menu_number(data_set)

    elif (number) == 2:
        x = input("Give a date (dd.mm): ")
        avgDay(x, data_set)
        lowHigh(x, data_set)
        rain(x, data_set)
        print_menu()
        # passing data_set to preserve it
        menu_number(data_set)

    elif (number) == 3:
        avgMonth(data_set)
        avgLow(data_set)
        avgHigh(data_set)
        print_menu()
        # passing data_set to preserve it
        menu_number(data_set)

    elif (number) == 4:
        scatPlot(data_set)
        print_menu()
        # passing data_set to preserve it
        menu_number(data_set)

    elif (number) == 0:
        sys.exit()

    else:
        print("\n Your selection is invalid, please try again!\n")
        print_menu()
        # passing data_set to preserve it
        menu_number(data_set)

In this example, data_set is an optional variable. If you call menu_number(), data_set is None. But on your calls of menu_number(data_set), you can reuse the value.

Making data_set an optional parameter will prevent any undefined errors. Passing it back to itself will prevent you from needing to read the csv file over and over again.

Sign up to request clarification or add additional context in comments.

9 Comments

Hmm, this could be what I am missing, is there someway to upload one of the files I am using along with the question in here?
Honestly not sure. If you just pasted in a few rows of the csv in a code block, like you did with your function, that would do the trick for me. I expanded my example to show the entire function update.
Added in first few lines from one of the csv files I am working with, will test out what you suggested to see if that resolves my problems thanks.
Thanks. If you have trouble let me know. I tested with that and spotted another bug, in some of your function you have 'for line in data[1:]', but the variable you pass is data_set. So you'll need to update that too.
Again, thank you so much, haven't had much practical experience with python and the tutorials I have been going through haven't dealt with passing return values through multiple functions like I needed.
|
0

1) you must do data_set = loadFile() in order to recieve the list loadFile() returns.

2) now, regarding the "local variable 'data_set' referenced before assignment" error, it probably happens when number is not equal to one, which causes your code to skip data_set = loadFile(), and combined with the fact that data_set is not recognized outside of the if statement as long as you don't declare it in a higher scope (the beginning of the function, for example), function like avgDay(x, data_set) will not recognize data_set as a variable. to solve this i suggest:

1) declare data_set in a higher scope.

2) every action the user can choose that relays on data_set being initialized in loadFile() must also include this initialization

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.