【问题标题】:Library import in Python does not work as expectedPython 中的库导入无法按预期工作
【发布时间】:2022-01-05 13:10:27
【问题描述】:

我在执行这个 Python 代码时遇到了一个奇怪的错误。

import tensorflow as tf
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(2,)),
  tf.keras.layers.Dense(10, activation='sigmoid'),
])
model.compile(optimizer='adam',
              loss='mae',
              metrics=['mse'])
model.summary()

导致以下错误:

ModuleNotFoundError: No module named 'keras'

(我已经在 google Colab 上尝试过相同的代码,它可以工作)。

对我来说奇怪的是,这段代码在同一台机器上运行没有错误(这意味着所有库都在那里):

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Flatten, Dense

model = Sequential([
  Flatten(input_shape=(28, 28)),
  Dense(10, activation='softmax')
])

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

并且,如果在 jupyter 笔记本中我先执行第二个版本,然后执行第一个版本,我不会遇到错误。

这种行为的原因可能是什么以及如何解决?我正在使用带有 miniconda 的 Python 3.9.7。

更新 1:从 tensorflow 2.6.0 降级到 tensorflow 2.4.1 时,这种行为似乎消失了。

更新 2:按要求完成回溯:

---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
/tmp/ipykernel_19355/718649126.py in <module>
----> 1 model = tf.keras.models.Sequential([
      2   tf.keras.layers.Flatten(input_shape=(28, 28)),
      3   tf.keras.layers.Dense(10, activation='softmax')
      4 ])
      5 

~/miniconda3/envs/tf/lib/python3.9/site-packages/tensorflow/python/util/lazy_loader.py in __getattr__(self, item)
     60 
     61   def __getattr__(self, item):
---> 62     module = self._load()
     63     return getattr(module, item)
     64 

~/miniconda3/envs/tf/lib/python3.9/site-packages/tensorflow/python/util/lazy_loader.py in _load(self)
     43     """Load the module and insert it into the parent's globals."""
     44     # Import the target module and insert it into the parent's namespace
---> 45     module = importlib.import_module(self.__name__)
     46     self._parent_module_globals[self._local_name] = module
     47 

~/miniconda3/envs/tf/lib/python3.9/importlib/__init__.py in import_module(name, package)
    125                 break
    126             level += 1
--> 127     return _bootstrap._gcd_import(name[level:], package, level)
    128 
    129 

~/miniconda3/envs/tf/lib/python3.9/importlib/_bootstrap.py in _gcd_import(name, package, level)

~/miniconda3/envs/tf/lib/python3.9/importlib/_bootstrap.py in _find_and_load(name, import_)

~/miniconda3/envs/tf/lib/python3.9/importlib/_bootstrap.py in _find_and_load_unlocked(name, import_)

~/miniconda3/envs/tf/lib/python3.9/importlib/_bootstrap.py in _call_with_frames_removed(f, *args, **kwds)

~/miniconda3/envs/tf/lib/python3.9/importlib/_bootstrap.py in _gcd_import(name, package, level)

~/miniconda3/envs/tf/lib/python3.9/importlib/_bootstrap.py in _find_and_load(name, import_)

~/miniconda3/envs/tf/lib/python3.9/importlib/_bootstrap.py in _find_and_load_unlocked(name, import_)

~/miniconda3/envs/tf/lib/python3.9/importlib/_bootstrap.py in _call_with_frames_removed(f, *args, **kwds)

~/miniconda3/envs/tf/lib/python3.9/importlib/_bootstrap.py in _gcd_import(name, package, level)

~/miniconda3/envs/tf/lib/python3.9/importlib/_bootstrap.py in _find_and_load(name, import_)

~/miniconda3/envs/tf/lib/python3.9/importlib/_bootstrap.py in _find_and_load_unlocked(name, import_)

~/miniconda3/envs/tf/lib/python3.9/importlib/_bootstrap.py in _call_with_frames_removed(f, *args, **kwds)

~/miniconda3/envs/tf/lib/python3.9/importlib/_bootstrap.py in _gcd_import(name, package, level)

~/miniconda3/envs/tf/lib/python3.9/importlib/_bootstrap.py in _find_and_load(name, import_)

~/miniconda3/envs/tf/lib/python3.9/importlib/_bootstrap.py in _find_and_load_unlocked(name, import_)

ModuleNotFoundError: No module named 'keras'

【问题讨论】:

  • 这可能会有所帮助。 Another SO query on Keras import
  • 谢谢。目前感觉是tensorflow版本的问题。
  • 从 tensorflow 2.6.0 降级到 tensorflow 2.4.1 时解决了这个问题。无论如何我都会留下这个问题,以防有人明白发生了什么。
  • 你应该添加完整的回溯,没有它的上下文错误是没有意义的。
  • @Dr.Snoopy 完成。也许你明白发生了什么

标签: python-3.x tensorflow


【解决方案1】:

当前版本的 tensorflow 中似乎存在一个错误,尤其是模块 tensorflow.python.util.lazy_loader 中定义的 LazyLoader 类中的 _load() 方法。我想我们可以把它留到修复之前。我想深入探讨这里提出的另一个问题:为什么您的第二段代码有效,而第一段代码却失败了?

原因来自于导入系统以及Python中的点运算符。

在import m1.m2.m3 或from m1.m2.m3 import n1 语句中,m1.m2.m3 中的点符号用于分隔模块(包)和子模块(子包)的名称。它不是真正的点运算符。在处理这条语句时,Python 会首先导入模块(包)m1,然后是m1.m2,然后是m1.m2.m3。在加载模块的每个步骤中,都会出现两个显着的副作用(在许多其他操作中):

  • 待导入包的__init__.py文件被执行。
  • 在父模块的命名空间中放置了一个绑定到子模块对象。对于本例,m1.__dict__['m2'] 设置为模块对象m1.m2,m1.m2.__dict__['m3'] 设置为模块对象m1.m2.m3。

对于真正的点运算符,例如表达式obj1.attr1,计算顺序将是:

  1. 评估obj1.__getattribute__('attr1')并返回值
  2. 如果在第一步中没有找到这样的属性,则评估odj1.__getattr__('attr1')

obj1.__dict__['attr1'] 的搜索在第一步启动。

回到tensorflow,tensorflow包下的__init__.py中有这样的语句:

keras = _LazyLoader("keras", globals(), _keras_module)

这是您的示例的简化“第二版”,如下所示:

from tensorflow.keras.models import Sequential 
# tensorflow.__dict__['keras'] is set to be the module tensorflow.keras
import tensorflow as tf # make the module name tensorflow useable

print(type(tf.keras)) # tf.keras is evaluated to the submodule tensorflow.keras
# output: <class 'module'>

原来绑定到子模块对象的名称会覆盖__init__.py 中的绑定(赋值)。

但是如果我们不导入子模块tensorflow.keras,那么__init__.py中的绑定就可以了:

import tensorflow as tf

print(type(tf.keras))
# output: <class 'tensorflow.python.util.lazy_loader.LazyLoader'>

这解释了为什么您的第二种方法有效但第一种方法失败了。


参考:

对于导入机制:

对于点运算符:

【讨论】:

    【解决方案2】:

    您可以使用from tensorflow import keras 并再次尝试执行相同的代码。

    如果再次显示相同的错误,则在jupyter notebook 中运行以下代码:

    import keras
    print(keras.__version__)
    import tensorflow
    print(tensorflow.__version__)
    

    如果您发现版本之间存在一些差异,请在jupyter notebook 中执行以下代码,这将自动安装升级和兼容版本的 tensorflow 和 keras 以及其他所需的库。

    !pip insatll tensorflow
    import tensorflow
    print(tensorflow.__version__)
    
    !pip install keras
    import keras
    print(keras.__version__)
    

    如果问题仍然存在,请告诉我们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-16
      • 1970-01-01
      相关资源
      最近更新 更多