简体   繁体   English

Python模块(部分)彼此导入

[英]Python modules (partially) importing from each other

I'm breaking up a large-ish (for me anyway!) project into 2 or 3 modules, including a 'main' module with the top level menu etc. It will import a two or three 'sub-modules' for different aspects of the application. 我将一个大型项目(无论如何对我来说!)分解为2或3个模块,包括带有顶层菜单等的“主”模块。它将针对不同方面导入两个或三个“子模块”的应用程序。 However those modules will need various settings etc from the main module. 但是,这些模块将需要从主模块进行各种设置等。 Yes, they could be passed as arguments but there are quite a few of them and they are liable to change. 是的,它们可以作为参数传递,但是其中有很多,它们很容易更改。 Different modules will need different sub-sets of the settings. 不同的模块将需要不同的设置子集。

I'd like to be able to have the subordinate modules simply 'reach back' for their settings as needed (sort of global across modules as it were). 我希望能够使下级模块根据需要简单地“返回”其设置(按原样在各个模块之间进行全局排序)。

Here is a mickie-mouse example of what I mean: 这是我的意思的老鼠示例:

test1: 测试1:

# dummy version of main / sub modules with mutual importing
# this is the 'main module'
# in this trivial example, it would be easy to make mode an argument of the function
# but as an alternatiove can test2 'reach back' to test1? 

from test2 import taskA
mode = 1
ans = taskA()
print(ans)

test2: 测试2:

# dummy version of main / sub modules with mutual importing
# this is the 'sub module' that executes taskA

from test1 import mode

def taskA():
    print('taska, mode = {0}'.format(mode))    
    return 'Hello World!'

mode = 0
print('test2 initialised')

And the results is 结果是

Traceback (most recent call last):
  File "C:\Python33\MyScripts\test1.py", line 6, in <module>
    from test2 import taskA
  File "C:\Python33\MyScripts\test2.py", line 4, in <module>
    from test1 import mode
  File "C:\Python33\MyScripts\test1.py", line 6, in <module>
    from test2 import taskA
ImportError: cannot import name taskA

Presumably this is due to potential circularity. 据推测这是由于潜在的圆形性。 (Though, if its able to detect the circularity - not hard in this case!, ie that taskA has already been imported, you'd think its able to simply break out of the circularity, as opposed to throwing an error). (但是,如果它能够检测到圆度-在这种情况下就不难了,也就是说,已经导入了taskA,您会认为它能够简单地突破圆度,而不是抛出错误)。

Is there a way to achieve this? 有没有办法做到这一点? There's several obvious ways to code around it - keep it as one module; 有几种显而易见的编码方法-将其作为一个模块保存; pass the settings as arguments (but that will have pitfalls if 'test2' has to modify any of the settings, if only as Im still getting my head around python's handling of mutable objects and binding); 将设置作为参数传递(但是如果'test2'必须修改任何设置,那将是一个陷阱,前提是Im仍然让我继续关注python对可变对象和绑定的处理)。 move all the settings to a separate module (test0) accessed by both test1 and test2. 将所有设置移动到一个单独的模块(test0),test1和test2均可访问。

Given that these modules are intimately connected (I believe the term is strongly coupled), logically it should all be one module. 鉴于这些模块紧密相连(我相信该术语是紧密耦合的),从逻辑上讲,它们应该全部是一个模块。 Except that its getting big. 除了它越来越大。

My question is twofold ... how best to do what I want; 我的问题是双重的……如何最好地做我想做的事; but also to understand why Python cant handle mutual imports. 还要了解为什么Python无法处理相互导入。

(1) Try moving your "mode = 1" line before the import. (1)尝试在导入之前移动“ mode = 1”行。 This makes it no longer sequentially dependent on the import statement. 这使得它不再顺序依赖于import语句。

(2) If that doesn't work, put the mode into a separate package and have both test1 and test2 import mode from there. (2)如果这不起作用,请将模式放入单独的程序包中,并从那里同时具有test1和test2导入模式。

The basic problem is that you've mingled levels of dependency. 基本问题是您已经混合了依赖性级别。 You created an artificial link between "mode" and other items in that module. 您在“模式”和该模块中的其他项目之间创建了人为链接。


I don't see where you're having trouble with setting "mode"; 我看不到您在设置“模式”时遇到了麻烦; I did it just fine on the first try. 我第一次尝试就做的很好。

test0.py test0.py

mode = 2

test1.py test1.py

from test0 import mode
from test2 import taskA
mode = 1
ans = taskA()
print(ans)

test2.py test2.py

from test0 import mode
def taskA():
    print('taska, mode = {0}'.format(mode))
    return 'Hello World!'

mode = 0
print('test2 initialised')

execution 执行

>>> python2.7 test1.py
test2 initialised
taska, mode = 0
Hello World!

>>> >>>

In your original example: (A) in test1.py, move the mode=1 line to before the import: 在您的原始示例中:(A)在test1.py中,将mode = 1行移动到导入之前:

mode = 1

from test2 import taskA
ans = taskA()
print(ans)

This switch shows that mode cannot depend on anything in module taskA, breaking the pathological circular dependence. 此开关表明模式不能依赖模块taskA中的任何内容,从而打破了病理循环依赖。

(B) Run the program with test2.py as the top-level module: (B)使用test2.py作为顶层模块运行该程序:

>>> python2.7 test2.py
test2 initialised
taska, mode = 0
Hello World!
test2 initialised

Does that get you where you want to be? 这样可以使您到达想要的位置吗?

In general, you should design your dependencies in a Directed Acyclic Graph (DAG). 通常,应在有向无环图(DAG)中设计依赖项。 C can be simple-minded, but good with this, separating header ( .h) and code ( .c) files. C可以很简单,但与此同时可以将标头( .h)和代码( .c)文件分开。 That's why I suggested the third file to hold your "mode" declaration. 这就是为什么我建议第三个文件保存您的“模式”声明。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM