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

时间:2019-07-19 22:38:52

标签: python-3.x python-3.7

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’

1 个答案:

答案 0 :(得分:0)

import config时,Python使用的是 config 文件夹(带有JSON文件的文件夹),而不是lib/config.py模块。您可以在导入后打印config.__path__来检查它:

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

_NamespacePath表示文件夹 config 被视为implicit Python package,它不像regular Python package一样包含__init__.py,但是名称与要导入的“ config”匹配。

  

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

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

由于<directory>/configimport config目标匹配,因此您的设置属于项目3。然后,您可能想知道<directory>是什么?这取决于存储在sys.path中的Module Search Path,这是Python将在其中寻找导入目标的所有目录的列表。当您在 root 下运行测试脚本时,会将 root 目录添加到您的sys.path中。

  

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

通过在 basestation_config.py 中的import config之前添加它来进行检查:

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

import config as config

这说明了原因。要解决此问题,您可以执行以下操作:

  1. config 文件夹重命名为其他名称(例如 jsonfiles ),只是为了防止此类将来的错误,并将其与 config.py < / em>模块
  2. 更改 lib 以遵循regular Python package structure,方法是在 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__ ”)。

现在这些更改后应该可以使用。