Search code examples
pythonfunctionpython-3.xdefined

global name 'doc' is not defined, trouble withvcall from one function to annother


I'm having some trouble with a piece of code I'm currently writing.

With the following code I get the NameError: global name 'doc' is not defined.

def createHtml():
    name = input("\nEnter the name for your HTML-page: ")   
    doc = open(name + ".html", 'w')

def createTitle():
    print (t[0], file=doc) #<!DOCTYPE html>
    print (t[1], file=doc) #<html>
    print (t[2], file=doc) #<head>
    title = input("Enter your title here: ")
    print ("  <title>",title,"</title>", file=doc)
    print (t[3], file=doc) #</head>

I know it's because the doc is only defined in the createHtml-function. But how do I get it to work if I want the same doc to work when called in a different function? I cant leave it out of the createHtml-function because it will mess up my program since I have a menu which allows the user to choose from the different functions. Like this:

while True:
    menu = input("\nPress 1 to enter the file name for the HTML-page"
                 "\nPress 2 to enter title for the HTML-page"
                 "\nPress 3 to start entering code in body"
                 "\nPress 4 to exit\n")
    if menu == "1":
        createHtml()
    elif menu == "2":
        createTitle()
    elif menu == "3":
        createBody()
    else:
        print ("Good bye!")
        break
doc.close()

And the doc is defined by the name variable in:

name = input("\nEnter the name for your HTML-page: ")

Is there anyway to get doc from the createHtml-function to my other functions?


Solution

  • What about wrapping the functions inside a class?

    class HtmlBuilder(object):
    
        def __init__(self):
            self.doc = None
    
        def createHtml(self):
            name = input("\nEnter the name for your HTML-page: ")   
            self.doc = open(name + ".html", 'w')
    
        def createTitle(self):
            print (t[0], file=self.doc) #<!DOCTYPE html>
            print (t[1], file=self.doc) #<html>
            print (t[2], file=self.doc) #<head>
            title = input("Enter your title here: ")
            print ("  <title>",title,"</title>", file=doc)
            print (t[3], file=self.doc) #</head>
    
        def Dispose(self):
            self.doc.flush()
            self.doc.close()
    

    And just use it like this:

    hb = HtmlBuilder()
    while True:
        menu = input("\nPress 1 to enter the file name for the HTML-page"
                     "\nPress 2 to enter title for the HTML-page"
                     "\nPress 3 to start entering code in body"
                     "\nPress 4 to exit\n")
        if menu == "1":
            hb.createHtml()
        elif menu == "2":
            hb.createTitle()
        elif menu == "3":
            hb.createBody()
        else:
            print ("Good bye!")
            break
    
    hb.Dispose()
    

    At the end of the day, this is a perfect use case for Object Oriented Programming isn't it? After this, a lot of good improvements can be done.

    For example:

    1. Replace the print statements from the function to the outer code.
    2. Make your methods testable.
    3. Unit testing.
    4. GOOD STUFF :D