使用portlib.import_MODULE时的模块未创建错误

2022-03-31 00:00:00 python python-3.x python-import

问题描述

我有以下文件夹结构,并且在util.py中有一个测试方法。当运行util方法时,我看到在我试图获取所有类的模块中导入的模块出现错误。

Parent
--report <dir>
----__init__.py
----AReport.py
----names_list.py
--util.py

util.py

import inspect
import importlib
import importlib.util

def get_class_names(fileName):
    for name, cls in inspect.getmembers(importlib.import_module(fileName, package='report'), inspect.isclass):
        print(name, cls)

if __name__ == '__main__':
    get_class_names('report.names_list')

Names_list.py

from AReport import AReport

class Team:
    name = ""
    def __init__(self, name):
        self.name = name

class Names_List(AReport):
    def __init__(self, name=None):
        AReport.__init__(self, name)

    def test(self):
        print('In test')        

AReport.py

from abc import ABCMeta, abstractmethod

class AReport(metaclass=ABCMeta):
    def __init__(self, name=None):
        if name:
            self.name = name

    def test(self):
        pass

当我从util运行测试方法时,我收到以下错误:

ModuleNotFoundError: No module named AReport

解决方案

假设您没有使用sys.pathPYTHONPATH更改任何内容,则问题是AReport模块不是util.py中的可见模块。

您可以通过在util.py的顶部添加以下内容进行检查:

import sys
print(sys.path)

这将打印出解释器查找模块的所有路径的列表。您将看到那里只有Parent模块的路径,因为这是util.py运行的位置。这在The Module Search Path文档中进行了解释:

导入名为spam的模块时,解释器首先搜索 用于具有该名称的内置模块。如果未找到,则它将搜索 提供的目录列表中名为spam.py的文件 变量sys.pathsys.path从以下位置初始化:

  • 包含输入脚本的目录(或当前目录 未指定文件时)。
  • (目录名的列表,语法与 外壳变量PATH)。
  • 取决于安装的默认设置。

当您从父目录(包含输入脚本的目录)运行util.py时,

from AReport import AReport
它将从父目录中查找AReport模块,但它不在那里,因为只有report包直接位于/Path/to/Parent目录下。这就是为什么Python会引发ModuleNotFoundError。如果您这样做了

from report.AReport import AReport

它将正常工作,因为report包位于/Path/To/Parent下。

如果要在导入时避免使用report.前缀,一种选择是将report包添加到sys.pathutil.py

import sys
sys.path.append("./report")

print(sys.path)
# should now show the /path/to/Parent/report on the list
然后,您的from AReport导入现在将起作用。另一种选择是在运行util.py之前将/Path/to/Parent/Report添加到PYTHONPATH环境变量中。

export PYTHONPATH=$PYTHONPATH:/path/to/Parent/report

我通常使用PYTHONPATH选项进行测试,因此不需要修改代码。

相关文章