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’
答案 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>/config
与import 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
这说明了原因。要解决此问题,您可以执行以下操作:
更改 lib 以遵循regular Python package structure,方法是在 lib 下添加一个__init__.py
文件,以将其明确标记为包。
lib
├── __init__.py
├── 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__
”)。
现在这些更改后应该可以使用。