'Unique import * only allowed at module level

I am making a utility program which has multiple programs built into it but I made some changes to my program for it re-run when the user has prompted which then for some reason, I am facing the error

import * only allowed at module level

Here's my code

def main():
    
    import os
    import sys
    import time
    import pywhatkit as whatsapp
    from speedtest import Speedtest
    from tkinter import *
    from tkinter import messagebox
    from os import listdir
    from PIL import Image

    print("*"*30)
    print("Utility Build v1: Starting")
    print("*"*30)

    time.sleep(3)

    print("NOTE: Before using this program for repairing corrupted disk, please locate this utility .py file into the corrupted storage. Thanks")

    time.sleep(3)

    print("*"*30)
    print("*"*30)
    print("Commands: Choose by inputting allocated number")

    print("Utility 1: Speed Test")
    print("Utility 2: Whatsapp Message Automation")
    time.sleep(2)
    print("Please Wait...Loading")
    time.sleep(4)
    print("Utility 3: Disk/Removable Storage Repair(a.k.a Dr Corrupt)")
    print("Utility 4: Python .py status monitor")

    print("*"*30)
    print("*"*30)
    print("q = Quit Utility Program")

    input_ = input(": ")

    if input_ == "q":
        exit()
       
    if input_ == "1":

        time.sleep(2)

        print("*"*30)
        print("Speed Test: Starting")
        print("*"*30)
        
        st = Speedtest()

        Download_ = print("Your connection download speed is:", st.download())
        Upload_ = print("Your connection upload speed is:", st.upload())
        Download1_ = st.download()
        Upload1_ = st.upload()

        print("*"*30)
        print("Speed Test: Finishing Up!")
        print("*"*30)

        answer = input("Would you like results? ")

        if answer == "yes":
            print("NOTE: The first 2 digits frm the left is your internet speed")
            time.sleep(2)
            top = Tk()
            top.geometry("100x100")
            messagebox.showinfo("Speed Test: Download", Download1_)
            top.mainloop()

            reply = input("Would like to leave Utility Build(yes) or go to home page?(no) ")

        else:
            reply1 = print("Would like to leave Utility Build(yes) or go to home page?(no) ")
            if reply1 == "yes":
                main()
            else:
                exit()

    if input_ == "2":
        whatsapp.sendwhatmsg("+61450776320", "Hi, this is a test", 0, 0)

    if input_ == "3":
        
        for filename in listdir('./'):
          if filename.endswith('.png'):
            try:
              img = Image.open('./'+filename) # open the image file
              img.verify() # verify that it is, in fact an image
            except (IOError, SyntaxError) as e:
              print('Bad file:', filename) # print out the names of corrupt files


Solution 1:[1]

"Module level" just means in a part of the script that's not in a class or function. Any names you define there go directly into the module namespace.

The error message is therefore just saying to move

def main():
    
    import os
    import sys
    import time
    import pywhatkit as whatsapp
    from speedtest import Speedtest
    from tkinter import *
    from tkinter import messagebox
    from os import listdir
    from PIL import Image

to

import os
import sys
import time
import pywhatkit as whatsapp
from speedtest import Speedtest
from tkinter import *
from tkinter import messagebox
from os import listdir
from PIL import Image

def main():

Actually, the interpreter only really cares about the line from tkinter import *. The others are a matter of convention and readability.

CPython does optimizations on the local namespace inside a function that requires the interpreter to know the names of all local variables up-front. A star import prevents that from happening since you don't know what names will be in the imported module until you run it. The global namespace doesn't have this restriction, so you can do star imports there.

Python is a language for consenting adults. Just because something is "bad practice" or not maintainable does not make it a syntax error.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1