Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Why am I getting either error “local variable referenced before assignment” or “

ID: 3843111 • Letter: W

Question

Why am I getting either error “local variable referenced before assignment” or “global variable not defined”?

First of all, apologies for the very long, very terrible code below. It is work in progress and I pasted all of it in because it will probably need to be run in order to find where the problem is.

I am getting the error code "local variable 'dennisov_type' referenced before assignment" and I assume it is because I am trying to reference it from an outer level (outside of the indent). However I have tried to make the variable that is to be referenced (dennisov_type) a global variable by typing "global dennisov_type" on the line before the if statements, as well as after, inside the the function, outside of it, pretty much everywhere I could. But I am then getting the error code "global name 'dennisov_type' is not defined" when I do that, even though it IS defined.

The code appears after an option is selected from the dropdown box in the Tkinter window and the 'select' button is pressed.

Would someone mind running this for me in a Python editor and letting me know where I have gone wrong please?

Explanation / Answer

Okay, I found the problem.

In function display_choice(), at line number 56, you are assigning the following,

dennisov_type_selection = (dennisov_type_dropdown.get() + ' ')

And in all the if statements, you are checking the variable dennisov_type_selection with a string without the trailing newline. As a result of this, all if and elif statements are coming as false and your local variable dennisov_type is not getting initialized upon which when you're trying to use the value of this variable dennisov_type at line number 76, you're getting error.

What I've have done is, I removed the newline character you're adding to dennisov_type_selection at line number 56 and it is working fine.

Check this code:

from Tkinter import Tk, Button, Canvas, END, Spinbox
from ttk import Progressbar, Combobox
from urllib import urlopen
from re import findall
import re
import itertools

## Create a window
window = Tk()

## Give the window a title
window.title('Watch finder')

## Types of Dennisov watches
dennisov_type_list = ['Barracuda Limited','Barracuda Chronograph',
                      'Barracuda Mechanical','Speedster','Free Rider',
                      'Nau Automatic','Lady Flower','Enigma','Number One']

dennisov_file = open('dennisov_url.html', 'w')

dennisov_file.write('''
<!DOCTYPE html>
<html>
    <head>
        <title>Watches</title>
    </head>
    <body>
''')

#### Display the quanity of watches available for each type
##quantity_box = len(watch_option)
##
####
##for watch, number in enumerate(watch_option):

##    watch_number_name = watch_option[number][0]
##    watch_number_image = watch_option[number][1]
##    watch_number_price = watch_option[number][2]
##    watch_number_link = watch_option[(number)][3]
####    dennisov_file.write('<h1>' + watch_number_name + '</h1>')
##    print watch_number_image
####    dennisov_file.write('<img src="' + watch_number_image + '"> ')
##    print watch_number_price
####    dennisov_file.write('<h2>' + watch_number_price + '</h2>')
##    print watch_number_link
####    dennisov_file.write('<a href="'+watch_number_link+'">'+watch_number_link+'</a>')
##     

dennisov_file.write('''
</body>
</html>
''')

## Define function for ...............
def display_choice():
    dennisov_type_selection = (dennisov_type_dropdown.get())
    if dennisov_type_selection == 'Barracuda Limited':
        dennisov_type = 'barracuda_chronograph'
    elif dennisov_type_selection == 'Barracuda Chronograph':
        dennisov_type = 'barracuda_chronograph'
    elif dennisov_type_selection == 'Barracuda Mechanical':
        dennisov_type = 'barracuda_mechanical'
    elif dennisov_type_selection == 'Speedster':
        dennisov_type = 'speedster'
    elif dennisov_type_selection == 'Free Rider':
        dennisov_type = 'free_rider'
    elif dennisov_type_selection == 'Nau Automatic':
        dennisov_type = 'nau_automatic'
    elif dennisov_type_selection == 'Lady Flower':
        dennisov_type = 'lady_flower'
    elif dennisov_type_selection == 'Enigma':
        dennisov_type = 'enigma'
    elif dennisov_type_selection == 'Number One':
        dennisov_type = 'number_one'

    dennisov_url = 'https://denissov.ru/en/'+ dennisov_type + '/'
    dennisov_url_subpage = dennisov_url[19:]

    ## Make the html document just created equal to an opened and read URL????
    ##???????????????????????????????????????????????????????????????????
    dennisov_html = urlopen(dennisov_url).read()
    ## Replace instances of double quotation marks in the text with singles
    ## so that the findall regex code does not get confused
    dennisov_html = dennisov_html.replace('"', "'")

    ## Find all of the images of the watches. Each watch image starts with the text
    ## "img src=". Do not match those with any" symbols in the URL
    watch_image_urls = findall("<img src="(/files/collections/o[^"]*)'", dennisov_html)
    ## Add the URL domain to each watch image subpage to create full addresses
    watch_image_urls = ['https://denissov.ru' + remainder for remainder in watch_image_urls]

    ##    dennisov_file.write('        <img src="' + image + '"> ')

    ## Return the watch type. The watch type is in a title tag called "titlusref"
    ## and can be any combination of letters and spaces, followed by a space and
    ## "<" symbol.
    watch_type = findall("titlusref'>([a-zA-Z]+ *[a-zA-Z]*) *<", dennisov_html)[0]

    ## Find all of the links when each watch is clicked. Each watch link starts
    ## with the text "a href="followed by the subpage, followed by any<br/>     ## letter, number and"_" symbol combination, followed by a backslash
    watch_link_urls = findall("a href="" + (dennisov_url_subpage) + "([A-Za-z0-9_]+/)", dennisov_html)<br/>     ## Add the main URL to each watch subpage<br/>     watch_link_urls = [str(dennisov_url) + remainder for remainder in watch_link_urls]</p> <p>    ## Find all of the model numbers of each watch. Each model starts with the text<br/>     ## "covername" then any combination of letters, dots and spaces.<br/>     watch_models = findall("covername">([A-Z a-z0-9.]+)", dennisov_html)
    ## Add the watch type to each watch model, seperated by a space, to create the
    ## full watch names
    watch_names = [str(watch_type) + " " + remainder for remainder in watch_models]

    ## Get current USD to AUD exchange rate using a known currency website
    currency_converter_url = 'http://www.xe.com/currencyconverter/convert/?From=USD&To=AUD'
    currency_html = urlopen(currency_converter_url).read()
    ## Replace instances of double quotation marks in the text with singles
    ## so that the findall regex code does not get confused
    currency_html = currency_html.replace('"', "'")
    ## Find the exchange rate. The exchange rate starts with "uccResultAmount'>"
    ## and is then followed by any combination of numbers with a decimal place
    exchange_rate = float(findall("uccResultAmount'>([0-9]+.[0-9]*)", currency_html)[0])

    ## Find the price of the models and make into floats. Each model price contains
    ## numbers followed by the text "USD"
    USD_watch_price = [float(price) for price in (findall("([0-9]*) usd", dennisov_html))]
    ## Convert the USD watch prices to current AUD prices and round to 2 decimals
    watch_price = [round(exchange_rate*price, 2) for price in USD_watch_price]
    ## Add the currency to the prices
    watch_price = ["AU $" + str(price) for price in watch_price]

    ## Match each watch name to its image and URL inside a tuple and place each
    ## tuple inside a list
    watch_list = zip(watch_names, watch_image_urls, watch_price, watch_link_urls)
    ## For each watch tuple (matching image, name and URL), assign a watch number
    watch_option = {'watch_{}'.format(i): e for i, e in enumerate(watch_list)}

## Create a spinbox
    spinbox_list = []
    spinbox_grid_list = []
    for watch, number in enumerate(watch_names):
        spinbox = 'spinbox_' + str(watch) + ' = Spinbox(window, width = 5, from_=0, to=10)'
        spinbox_grid = 'spinbox_' + str(watch) + '.grid(padx = 2, pady = 2, row = ' + str(1+ 4*watch) +', column = 0)'
        spinbox_list.append(spinbox)
        spinbox_grid_list.append(spinbox_grid)
        spinbox_option = {'spinbox_{}'.format(i):e for i, e in enumerate(spinbox_list)}
    spinbox_option_string = ' '.join(spinbox_option.values())
    spinbox_grid_option = {'spinbox_grid_{}'.format(i):e for i, e in enumerate(spinbox_grid_list)}
    spinbox_grid_option_string = ' '.join(spinbox_grid_option.values())
    exec(spinbox_option_string)
    exec(spinbox_grid_option_string)

## Create the dropdown box for the Dennisov watch types
dennisov_type_dropdown = Combobox(window, width = 25,
                                  values = dennisov_type_list)

## Create the Dennisov model selection canvas
dennisov_model_selection = Canvas(window, width = 400, height = 500,
                                  bg = 'white')

## Create Dennisov type selection button
dennisov_select_button = Button(window, text = 'Select',
                                command = display_choice)

## Locate elements on grid
dennisov_type_dropdown.grid(pady = 2, padx = 2, row = 0, column = 1)
dennisov_model_selection.grid(padx = 2, pady = 2, row = 1,
                              column = 0, rowspan = 15, columnspan = 3)
dennisov_select_button.grid(pady = 2, padx = 2, row = 0, column = 2)

dennisov_file.close()
window.mainloop()