繁体   English   中英

Python3:模块“ x”没有属性“ y”

[英]Python3: module 'x' has no attribute 'y'

Python import语句使我感到困惑。 有人可以帮我解决这个问题吗?

文件树看起来像这样

root
+- notebook.ipynb
+- lib/
  +- basestation_config.py
  +- config.py
+- config/
  +- valence_pod.json
  +- etc…

config.py我有:

import json
import os

default_config_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'config'))

def read_filepath(filepath):
    with open(filepath, "r") as read_file:
        return json.load(read_file)

def read(filename):
    filepath = os.path.join(default_config_path, filename) + '.json'
    return read_filepath(filepath)

basestation_config.py我有:

import config as config
# … a buncha class libraries, including BasestationConfig
def read_basestation_config(config_name = 'valence_pod'):
    return BasestationConfig(config.read(config_name))

notebook.ipynb我有一个测试单元:

import lib.basestation_config as bsc
bs_config = bsc.read_basestation_config()
display(bs_config)

当我运行它时,我得到:

<module 'config' (namespace)>
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-1-f2942fb5fb2d> in <module>
      1 import lib.basestation_config as bsc
----> 2 bs_config = bsc.read_basestation_config()
      3 display(bs_config)

/mnt/eng_store/pod/logs/embedded/utils/logutils/indot-py/lib/basestation_config.py in read_basestation_config(config_name)
    270 def read_basestation_config(config_name = 'valence_pod'):
    271     print(config)
--> 272     return BasestationConfig(config.read(config_name))

AttributeError: module 'config' has no attribute ‘read’

当您import config ,Python使用的是config文件夹(一个带有JSON文件的文件夹),而不是lib/config.py模块。 您可以在导入后通过打印config.__path__进行检查:

import config as config
print(config.__path__)
# _NamespacePath(['/path/to/root/config']) 

_NamespacePath表示文件夹配置被视为隐式Python包 ,它不像常规Python包一样包含__init__.py ,但名称与导入的“ config”匹配。

在为父路径中的每个目录查找名为“ foo”的模块或软件包时:

  • 如果找到<directory>/foo/__init__.py<directory>/foo/__init__.py导入并返回常规包。
  • 如果没有,则找到<directory>/foo.{py,pyc,so,pyd} ,将导入并返回一个模块。 扩展的确切列表因平台以及是否指定-O标志而异。 这里的列表是代表性的。
  • 如果不是,而是找到<directory>/foo并且它是一个目录,则会记录该目录,并且扫描将继续使用父路径中的下一个目录。
  • 否则,扫描将继续使用父路径中的下一个目录。

您的设置属于项目符号3,因为<directory>/configimport config目标匹配。 然后,您可能想知道这里的<directory>是什么? 这取决于存储在sys.path模块搜索路径 ,该路径是Python将在其中查找导入目标的所有目录的列表。 当您在root用户下运行测试脚本时, sys.path 目录添加到sys.path

包含正在运行的脚本的目录位于搜索路径的开始,在标准库路径之前。

通过在basestation_config.py中 import config之前添加此选项来进行检查:

import sys
print(sys.path)
# ['/path/to/root', ... ]

import config as config

这就解释了为什么。 要解决此问题,您可以执行以下操作:

  1. config文件夹重命名为其他名称(例如jsonfiles ),只是为了防止将来发生此类错误并将其与config.py模块区分开
  2. 更改lib以遵循常规的Python包结构 ,方法是在lib下添加__init__.py文件以将其明确标记为包。

     lib ├── __init__.py ├── basestation_config.py └── config.py 
  3. 最后,在basestation_config.py中明确指出要在同一目录中导入config.py
     from . import config as config print(config.__file__) # /path/to/lib/config.py 

请注意,在执行第3步之前,如果您早先添加了print(config.__path__) ,请确保在应用更正后的代码后将其删除 ,因为它很可能在config.py中不可用(您可能会收到“ AttributeError:模块'lib.config'没有属性__path__ “)。

这些更改之后,它现在应该可以工作了。

暂无
暂无

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

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