You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python循环导入引发ImportError及跨模块函数调用问题求助

问题分析与解决

1. 循环导入问题

你遇到的ImportError确实是循环导入导致的:

  • toolkit.py在顶部从backups模块导入backups类
  • backups.py又在顶部从toolkit模块导入main类
    两个模块互相依赖,Python解释器加载时无法完成初始化流程,因此抛出该错误。

解决循环导入的方法

方法一:延迟导入(快速修复)

把跨模块的导入语句移到函数内部,避免在模块初始化阶段触发互相依赖:
修改backups.py,将from toolkit import main移到check_backups函数内部:

from utilities import bcolors, utility

class backups:
    def __init__(self, my_dirs, my_files, curdir): 
        self.my_dirs = [] 
        self.my_files = [] 
        self.curdir = '' 

    def check_backups():
        from toolkit import main  # 延迟导入,仅在函数执行时加载
        print(bcolors.CRED + "Check Backups..." + bcolors.ENDC)
        main.menu_backup()

方法二:重构代码结构(长期推荐)

让backups.py只负责备份业务逻辑,不反向调用菜单控制逻辑,把菜单跳转的逻辑统一放在toolkit.py中,彻底消除跨模块的循环依赖。

2. 函数调用的问题

你的代码中还有类方法调用的错误,需要同步修正:

(1)类方法定义问题

main和backups类中的方法都是用普通函数定义的,但你直接用类名调用(比如main.main()),这会因为缺少self参数报错。需要将这些方法定义为静态方法:

  • 修改toolkit.py的main类:
class main():
    @staticmethod  # 添加静态方法装饰器
    def main():
        # 原代码逻辑不变
        ...
    
    @staticmethod
    def menu_backup():
        # 原代码逻辑不变
        ...
  • 修改backups.py的check_backups方法:
class backups:
    def __init__(self, my_dirs, my_files, curdir): 
        self.my_dirs = [] 
        self.my_files = [] 
        self.curdir = '' 

    @staticmethod
    def check_backups():  # 移除未使用的ln参数
        from toolkit import main
        print(bcolors.CRED + "Check Backups..." + bcolors.ENDC)
        main.menu_backup()

(2)修正调用逻辑

修改后,toolkit.py中backups.check_backups()的调用就可以正常执行了。

修正后的完整代码示例

toolkit.py

from utilities import bcolors, utility
from backups import backups
import os
version = "1.0"

utility.UpdateNeeded()

class main():
    @staticmethod
    def main():
        print( bcolors.BOLD + "Toolkit" + bcolors.ENDC)

        print("")
        choose = int(input(bcolors.BOLD + "1"  + ": " + bcolors.CYELLOW + "Backups" + bcolors.ENDC + "\n\
"+bcolors.BOLD + "0"  + ": " + bcolors.CYELLOW + "Close" + bcolors.ENDC + "\n\
> "))
        if choose == 0:
            print(bcolors.CGREEN + "Ciao." + bcolors.ENDC)
            exit()
        if choose == 1:
            os.system('cls')
            main.menu_backup()

    @staticmethod
    def menu_backup():
        choose = int(input(bcolors.BOLD + "1"  + ": " + bcolors.CYELLOW + "Check Backups" + bcolors.ENDC + "\n\
"+bcolors.BOLD + "0"  + ": " + bcolors.CYELLOW + "Main Menu" + bcolors.ENDC + "\n\
> "))
        if choose == 0:
            os.system('cls')
            main.main()
        if choose == 1:
            os.system('cls')
            backups.check_backups()

main.main()

backups.py

from utilities import bcolors, utility

class backups:
    def __init__(self, my_dirs, my_files, curdir): 
        self.my_dirs = [] 
        self.my_files = [] 
        self.curdir = '' 

    @staticmethod
    def check_backups():
        from toolkit import main
        print(bcolors.CRED + "Check Backups..." + bcolors.ENDC)
        main.menu_backup()

utilities.py

class bcolors:
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    CRED    = '\33[31m'
    CGREEN  = '\33[32m'
    CYELLOW = '\33[33m'

class utility:
    @staticmethod
    def UpdateNeeded():
        print("update check...")

总结

  1. 循环导入通过延迟导入(将导入放在函数内部)快速解决,长期建议重构代码减少模块间的双向依赖
  2. 类方法调用错误通过添加@staticmethod装饰器修正,确保可以用类名直接调用方法

内容的提问来源于stack exchange,提问作者Deluxe23

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 10:10:34