如何解决Python中的循环引用问题

3
我有一个类名为JCheq,其中有一个名为'logger'的静态变量。
JCheq导入了模块“printing_systems”,但我需要在“printing_systems”中使用“JCheq.logger”。
在将“import JCheq”放入“printing_systems.py”后,我的代码无法编译。
jcheq.py
from printing_systems import printing_systems
from logger import logger

class JCheq:
    logger = logger.Logger('logs/jcheq.log', loglevel=logger.Logger.INFO)

    def __init__(self):
        pass
    ...

printing_systems/printing_systems.py

from jcheq import JCheq
class WinLPR:

    def __init__(self):
        pass

    @staticmethod
    def send(spool, params):
        temp_dir = tempfile.mkdtemp()
        try:
            JCheq.logger.log('Creando archivo temporal en dir: ' + temp_dir, logger.Logger.TRACE)

错误追踪:

Traceback (most recent call last):
  File "/home/jsivil/Desktop/Proyectos/UNPAZ/jcheq/jcheq/jcheq.py", line 12, in <module>
    from printing_systems import printing_systems
  File "/home/jsivil/Desktop/Proyectos/UNPAZ/jcheq/jcheq/printing_systems/printing_systems.py", line 7, in <module>
    from jcheq import JCheq
  File "/home/jsivil/Desktop/Proyectos/UNPAZ/jcheq/jcheq/jcheq.py", line 12, in <module>
    from printing_systems import printing_systems
ImportError: cannot import name 'printing_systems'

printing_systems 模块中有一个名为 printing_systems 的变量吗?你正在尝试从模块中导入一个变量,而不是只导入 import printing_systems - Tadhg McDonald-Jensen
@BrianCain 是的,我把导入移到了方法中,现在它可以工作了,但我不知道这是否可行...你说的分解是什么意思? - JorgeeFG
@TadhgMcDonald-Jensen,jcheq.py在'root'目录下,然后还有像printing_systems这样的子目录。 - JorgeeFG
是的,抱歉,我意识到可以从回溯信息中获取该信息,但你确实有一个__init__.py文件,对吧? - Tadhg McDonald-Jensen
@TadhgMcDonald-Jensen,是的,一切都正常,只是现在我需要使用printing_systems.py中的JCheq.logger。 - JorgeeFG
显示剩余5条评论
1个回答

1
在函数中移动导入语句通常用于解决循环导入问题。在重新构建应用程序成本过高或者根本没有意义的情况下,这种方法非常方便。
另一种解决方法是将JCheq.logger移到自己的模块中,然后jcheq.pyprinting_systems/printing_systems.py都可以导入该模块。
或者,您可以使logger.Logger成为一个工厂函数,由某个注册表支持(或仅仅是memoize),以便当给定相同参数时返回相同的记录器。这样,printing_system.py只需导入logger而不是导入jcheq

好的,我选择了工厂方法,似乎可以工作。我发现它的一个问题是,由于导入printing_systems位于JCheq的顶部,因此我必须首先导入LoggerFactory,然后在其后立即将logger作为全局变量,然后再导入printing_systems。否则,printing_systems将首先被解析,并且将创建具有相同路径但不同log_level的记录器(因为log_level应该仅设置一次,它是一个可选参数)。 - JorgeeFG
你尝试过对 logger.Logger 进行记忆化吗?由于你正在使用 Python 3,你可以使用 functools.lru_cache 快速实现。我认为这将解决导入顺序问题。 - daragua

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接