Home > Net >  How to solve the circular import problem in python?
How to solve the circular import problem in python?

Time:08-03

I got the 2 following python files:

1: debug.py

import tkinter as tk
from tkinter import scrolledtext
from tkinter import *
from tkinter import ttk
from helper import show_msg

root = Tk()
root.geometry('900x500')
root.resizable(False, False)
root.title("test")

menu = ["elem1", "elem2"]
menu1 = ttk.Combobox(root, state="readonly",values=["choose"]   menu, width=55)
menu1.current(0)
menu1.pack()
menu1.bind("<<ComboboxSelected>>", show_msg(menu1))

debug_frame = tk.Frame(root)
debug_frame.pack()
debug_bar = scrolledtext.ScrolledText(debug_frame, width=100, height=5)
debug_bar.pack()

root.mainloop()

2: helper.py

import tkinter as tk
from debug import debug_bar

def print_msg_on_screen(msg):
    debug_bar.insert(tk.INSERT, msg)
    print(msg)

def show_msg(menu1):
    if(menu1.current() == 0):
        msg="choose an element"
        print_msg_on_screen(msg)
    if (menu1.current() == 1):
        msg = "you chose element1"
        print_msg_on_screen(msg)
    if (menu1.current() == 2):
        msg = "you chose element2"
        print_msg_on_screen(msg)

I wanna print whatever msg I get from show_msg from helper.py into the debug bar (in tkinter) that I declared in debug.py, but I keep getting this error :

ImportError: cannot import name 'show_msg' from partially initialized module 'helper' (most likely due to a circular import)

Is there a way to make this circular import work? Thank you in advance!

CodePudding user response:

It is better to pass debug_bar to show_msg() (which in turn passes to print_msg_on_screen()), so no need to import debug inside helper.py:

debug.py
...
# lambda should be used instead of direct calling show_msg()
menu1.bind("<<ComboboxSelected>>", lambda e: show_msg(menu1, debug_bar))
...
helper.py
import tkinter as tk

def print_msg_on_screen(msg, widget):
    widget.insert(tk.INSERT, msg '\n')
    print(msg)

def show_msg(menu1, widget):
    print(f'{menu1}')
    if(menu1.current() == 0):
        msg="choose an element"
        print_msg_on_screen(msg, widget)
    if (menu1.current() == 1):
        msg = "you chose element1"
        print_msg_on_screen(msg, widget)
    if (menu1.current() == 2):
        msg = "you chose element2"
        print_msg_on_screen(msg, widget)

CodePudding user response:

You're calling show_msg before debug_bar is defined (show_msg references print_msg_on_screen, which references debug_bar).

If you're not using show_msg and print_msg_on_screen anywhere else, I would move these both into debug.py, and order it like this:

def print_msg_on_screen(msg):
    ...

def show_msg(menu1):
    ...

debug_bar = ...

menu1.bind(..., show_msg(menu1))
  • Related