0

在我的项目中,我使用interaction包含一些“接口”的模块来访问系统功能。例如,我有 2 个模块实现不同的接口,其中一个依赖于其他接口。

模块1.py

value = 5

def init():
    pass

def provide_int():
    global value
    return value

模块2.py

def init():
    import interaction
    global value
    value = str(interaction.int_provider.provide_int())

def provide_string():
    global value
    return value

所以我想以同样的方式使用它:

交互.py

from importlib import import_module

globals()['int_provider'] = import_module('module1')
globals()['int_provider'].init()
globals()['str_provider'] = import_module('module2')
globals()['str_provider'].init()

因此,在初始化module2(调用 init 函数)期间,由于循环导入,我得到了 ImportError。这个例子当然是合成的,但常见的状态是一样的。

我有 2 个问题: 1. 像代理接口
一样使用“全局”模块是否正确? 2. 我怎样才能打败这种循环导入?interaction.py

4

2 回答 2

0

我建议取消这些init函数并让provide_string()函数在首次调用时设置其值。因为在模块加载时很少发生,所以模块相互引用不会有问题。此外,您可以interaction通过将as关键字与常规导入一起使用来简化模块:

迭代.py:

 import module1 as int_provider
 import module2 as string_provider

模块1.py:

 value = 5

 def provide_int():
     return value # no global statement necessary, since we don't assign to value

模块2.py:

 value = None # this will be set up after the first call to provide_string

 def provide_string():
     global value # global is needed, since we may assign a new string to value
     if value is None:
         import interaction
         value = str(interaction.int_provider.provide_int())
     return value
于 2013-09-27T12:02:03.277 回答
0

我怎样才能打败这种循环导入?

您可以使用django.utils.functional.SimpleLazyObject 之类的延迟创建的提供程序。这样,您将在访问提供程序的任何属性时对其进行初始化。您必须记住记住结果SimpleLazyObject因为传递的函数每次都会重新评估。

用法:

def init_str_provider():
    if not hasattr(init_str_provider, 'provider'):
        init_str_provider.provider = import_module('module2')
        init_str_provider.provider.init()
    return init_str_provider.provider

str_provider = SimpleLazyObject(init_str_provider)

像我interaction.py代理接口一样使用“全局”模块是正确的方法吗?

如果我要使用接口创建这样的结构,我宁愿选择:

  • 中的提供者类注册方法interfaces.py
  • 使用类来表示提供者(由于继承更容易接口!)。
  • 提供一个get_provider(name)函数interfaces.py以允许延迟提供程序初始化。

这种解耦使得测试和模拟单独的提供者变得更加容易,并为定制留下了更多的空间此外,如果您需要在另一个提供者中扩展一个提供者的行为,类对象将它们的状态存储在它们内部,而不是模块级别。这样,您实际上可以从其他提供者继承,而不必担心任何子提供者会修改独立的基本提供者的内部结构。

于 2013-09-27T12:05:48.800 回答