考虑下面的四段代码。其中,1、2和3都可以工作。我相信4和2类似,应该可以工作。但是它不可以。我得到了下面的错误:module 'tensorflow._api.v2.lite' has no attribute 'tools'
有什么区别?多级导入的行为与单级导入不同吗?
1.
from numpy import ones
a = ones((2, 2))
字符串
import numpy
a = numpy.ones((2, 2))
型
from tensorflow.lite.tools.flatbuffer_utils import read_model_with_mutable_tensors
read_model_with_mutable_tensors("model.tflite")
型
import tensorflow.lite.tools.flatbuffer_utils
tensorflow.lite.tools.flatbuffer_utils.read_model_with_mutable_tensors("model.tflite")
型
1条答案
按热度按时间ppcbkaq51#
好吧,所以这更像是一个猜测,但也许有人可以证实或反驳(不确定这是正确的词)我的理论。
首先,包和modules之间的区别很重要。模块是普通的.py文件,在这里你可以找到你的类,函数等。包是一种结构化模块的方式,就像文件夹结构一样。包可以有子包,可以有一个
__init__.py
文件来标记它们为包,并可以选择导入或声明一些东西。至于你的例子:
对于1,它非常简单。函数
ones
位于模块numpy
中,可以直接导入。请注意,您只导入了ones
,不能使用numpy
中的任何其他函数。在源代码中,
ones
实际上在numpy/core/numeric.py
中,但它有装饰器@set_module('numpy')
,这似乎将其移动到numpy.
导入中。在2中,您导入了整个
numpy
名称空间,然后可以调用它提供的所有函数,包括ones
。在3中,您可以通过包和子包导入。从文档中:
当导入包时,Python会在sys.path上的目录中搜索该包。
如果你检查source code,你可以看到这些导入的结构实际上是存在的,所以python可以用
sys.path
找到它。最困难的部分,4。
在这里,我不是100%确定python是如何管理导入的。
import tensorflow.lite.tools.flatbuffer_utils
个它导入模块
tensorflow
(至少对我来说,当我在IDE中检查变量时),我可以调用tensorflow.__version__
而不会出错。当我试图
import tensorflow.lite.tools.flatbuffer_utils as x
个或
tensorflow.lite.tools.flatbuffer_utils.read_model_with_mutable_tensors("model.tflite")
个它抛出了你提到的
ImportError
。似乎在这种情况下,python逐一检查了这些包的__init__.py
,并试图找到所有内容。在虚拟环境的site-packages文件夹中的
tensorflow
s__init__.py
中,行from ._api.v2 import lite
。(对我来说是在venv/Lib/site-packages/tensorflow/_api/v2/lite/__init__.py
中)。在这个__init__.py
中,没有tools
的导入,也没有tools
的子包(文件夹),这是ImportError
发生的部分。所以看起来对于一些导入,python使用sys.path
来查找函数的路径,有时它使用__init__.py
。我希望有一个更连贯和令人满意的答案,也许有更多知识的人可以扩展这个答案。