[英]python import circular dependency (and perhaps function declaration)
你好,我确实进入了循环依赖,除了加倍代码之外,什么不是重构的。
我有类似的东西(只有更复杂):
myParser.py:
import sys
import main #comment this to make it runnable
def parseEvnt():
sys.stdout.write("evnt:")
main.parseCmd(1) #comment this to make it runnable
tbl.py:
import myParser
tblx = {
1:("cmd",),
2:("evnt",myParser.parseEvnt),
}
main.py:
import tbl
def parseCmd(d):
print(tbl.tblx[d][0])
data=[1,2]
for d in data:
if(d<2):
parseCmd(d)
else:
fce = tbl.tblx[d][1]
fce()
我得到的明显错误是:
File "D:\Data\vbe\workspace\marsPython\testCircular2\main.py", line 1, in <module>
import tbl
File "D:\Data\vbe\workspace\marsPython\testCircular2\tbl.py", line 1, in <module>
import myParser
File "D:\Data\vbe\workspace\marsPython\testCircular2\myParser.py", line 2, in <module>
import main
File "D:\Data\vbe\workspace\marsPython\testCircular2\main.py", line 7, in <module>
parseCmd(d)
File "D:\Data\vbe\workspace\marsPython\testCircular2\main.py", line 3, in parseCmd
print(tbl.tblx[d][0])
AttributeError: module 'tbl' has no attribute 'tblx'
在CI中我想通过tbl.py
的声明告诉他有函数parseEvnt()
。 我不需要包含myParser
,也不会包含循环包含。
在python我不知道该怎么做。
我读了几个帖子,总有一些明智的人推荐重构。 但是,在这种情况下parseCmd()
需要看到tblx
这需要看parseEvnt()
除非函数声明)和parseEvnt()
需要调用parseCmd()
(COS evnt
包含触发cmd
,我不希望再次解码CMD码)。
有没有办法让它在python中工作?
应避免循环进口。 需要重构,任何仍需要循环导入的解决方法都不是一个好的解决方案。
话虽如此,重构不一定非常广泛。 至少有几个相当简单的解决方案。
由于您想要从多个地方使用parseCmd
,请将其移至单独的文件中。 这样, main.py
和myParser.py
都可以导入该函数。
parseCmd
传递给parseEvnt
。 首先,让parseEvnt
接受一个参数来告诉它运行哪个函数:
# myParser.py
import sys
def parseEvnt(parseCmd):
sys.stdout.write("evnt:")
parseCmd(1)
接下来,当您调用myParser.parseEvnt
,传入对main.parseCmd
的引用:
# main.py:
...
else:
fce = tbl.tblx[d][1]
fce(parseCmd)
还有其他方法可以完成同样的事情。 例如,您可以在myParser
添加“configure”方法,然后让main.py
调用configure
方法并传入对其parseCmd
的引用。 然后, configure
方法可以将此引用存储在全局变量中。
另一种选择是在使用它的函数中导入main:
main.py
import sys
def parseEvnt():
import main
sys.stdout.write("evnt:")
main.parseCmd(1)
如果你坚持不重构(这是真正的解决方案 - 不是一个聪明人),你可以将有问题的导入移动到myParser.py
的函数中
import sys
def parseEvnt():
import main ## import moved into function
sys.stdout.write("evnt:")
main.parseCmd(1)
再次,看看您是否可以重新设计代码,以避免这种相互依赖性。
上面的解决方案是一种破解,并不会解决由于这种依赖性而可能遇到的未来问题。
只要模块在完成所有导入之前不尝试使用彼此的数据,您就可以经常摆脱循环依赖 - 实际上,这意味着使用命名空间引用( from module import something
被禁止)并且仅使用函数和方法中的其他模块(全局空间中没有mystuff = module.mystuff
)。 那是因为当导入开始时,python将模块名称放在sys.modules
并且不会再尝试导入该模块。
你遇到了麻烦,因为当你运行main.py
,python会将__main__
添加到sys.modules
。 当代码最终import main
,模块列表中没有“main”,因此再次导入main.py
...并且它的顶级代码试图运行。
让我们重新安排你的测试用例并输入一些打印语句来告诉导入何时发生。
myParser.py
print(' + importing myParser')
import sys
print('import parsecmd')
import parsecmd
def parseEvnt():
sys.stdout.write("evnt:")
parsecmd.parseCmd(1)
tbl.py
print(' + importing tbl')
print('import myParser')
import myParser
tblx = {
1:("cmd",),
2:("evnt",myParser.parseEvnt),
}
Parsecmd.py(新)
print(' + importing parsecmd')
print('import tbl')
import tbl
def parseCmd(d):
print(tbl.tblx[d][0])
main.py
print('running main.py')
print('import parsecmd')
import parsecmd
if __name__ == "__main__":
data=[1,2]
for d in data:
if(d<2):
parsecmd.parseCmd(d)
else:
fce = parsecmd.tbl.tblx[d][1]
fce()
当我跑它时,我得到了
running main.py
import parsecmd
+ importing parsecmd
import tbl
+ importing tbl
import myParser
+ importing myParser
import parsecmd <-- didn't reimport parsecmd
cmd
evnt:cmd
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.