Search code examples
python-3.xtkinterspell-checkingtkinter-entrytkinter-text

Creating a python spellchecker using tkinter


For school, I need to create a spell checker, using python. I decided to do it using a GUI created with tkinter. I need to be able to input a text (.txt) file that will be checked, and a dictionary file, also a text file. The program needs to open both files, check the check file against the dictionary file, and then display any words that are misspelled.

Here's my code:

import tkinter as tk
from tkinter.filedialog import askopenfilename

def checkFile():
    # get the sequence of words from a file
    text = open(file_ent.get())
    dictDoc = open(dict_ent.get())

    for ch in '!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~':
        text = text.replace(ch, ' ')
    words = text.split()

    # make a dictionary of the word counts
    wordDict = {}
    for w in words:
        wordDict[w] = wordDict.get(w,0) + 1

    for k in dictDict:
        dictDoc.pop(k, None)
    misspell_lbl["text"] = dictDoc

# Set-up the window
window = tk.Tk()
window.title("Temperature Converter")
window.resizable(width=False, height=False)

# Setup Layout
frame_a = tk.Frame(master=window)
file_lbl = tk.Label(master=frame_a, text="File Name")
space_lbl = tk.Label(master=frame_a, width = 6)
dict_lbl =tk.Label(master=frame_a, text="Dictionary File")
file_lbl.pack(side=tk.LEFT)
space_lbl.pack(side=tk.LEFT)
dict_lbl.pack(side=tk.LEFT)

frame_b = tk.Frame(master=window)
file_ent = tk.Entry(master=frame_b, width=20)
dict_ent = tk.Entry(master=frame_b, width=20)
file_ent.pack(side=tk.LEFT)
dict_ent.pack(side=tk.LEFT)

check_btn = tk.Button(master=window, text="Spellcheck", command=checkFile)

frame_c = tk.Frame(master=window)
message_lbl = tk.Label(master=frame_c, text="Misspelled Words:")
misspell_lbl = tk.Label(master=frame_c, text="")
message_lbl.pack()
misspell_lbl.pack()

frame_a.pack()
frame_b.pack()
check_btn.pack()
frame_c.pack()

# Run the application
window.mainloop()

I want the file to check against the dictionary and display the misspelled words in the misspell_lbl.

The test files I'm using to make it work, and to submit with the assignment are here:

check file dictionary file

I preloaded the files to the site that I'm submitting this on, so it should just be a matter of entering the file name and extension, not the entire path.

I'm pretty sure the problem is with my function to read and check the file, I've been beating my head on a wall trying to solve this, and I'm stuck. Any help would be greatly appreciated.

Thanks.


Solution

  • The first problem is with how you try to read the files. open(...) will return a _io.TextIOWrapper object, not a string and this is what causes your error. To get the text from the file, you need to use .read(), like this:

    def checkFile():
        # get the sequence of words from a file
        with open(file_ent.get()) as f:
          text = f.read()
        with open(dict_ent.get()) as f:
          dictDoc = f.read().splitlines()
    

    The with open(...) as f part gives you a file object called f, and automatically closes the file when it's done. This is more concise version of

    f = open(...)
    text = f.read()
    f.close()
    

    f.read() will get the text from the file. For the dictionary I also added .splitlines() to turn the newline separated text into a list.

    I couldn't really see where you'd tried to check for misspelled words, but you can do it with a list comprehension.

    misspelled = [x for x in words if x not in dictDoc]
    

    This gets every word which is not in the dictionary file and adds it to a list called misspelled. Altogether, the checkFile function now looks like this, and works as expected:

    def checkFile():
        # get the sequence of words from a file
        with open(file_ent.get()) as f:
          text = f.read()
        with open(dict_ent.get()) as f:
          dictDoc = f.read().splitlines()
    
        for ch in '!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~':
            text = text.replace(ch, ' ')
        words = text.split()
    
        # make a dictionary of the word counts
        wordDict = {}
        for w in words:
            wordDict[w] = wordDict.get(w,0) + 1
        
        misspelled = [x for x in words if x not in dictDoc]
    
        misspell_lbl["text"] = misspelled