简体   繁体   English

使用 importlib.import_module 时出现 ModuleNotFoundError

[英]ModuleNotFoundError when using importlib.import_module

I have the following folder structure and I have a test method in util.py.我有以下文件夹结构,并且在 util.py 中有一个测试方法。 When the util method is run, I see an error with a module that is imported within the module where I am trying to get all classes.运行 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名称列表.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

When I run my test method from util, I get the following error:当我从 util 运行我的测试方法时,出现以下错误:

ModuleNotFoundError: No module named AReport

Assuming you did not change anything with sys.path or with PYTHONPATH , the problem is that AReport module is not "visible" from util.py.假设您没有对sys.pathPYTHONPATH任何更改,问题是AReport模块在AReport中不“可见”。

You can check this by adding this at the top of util.py :您可以通过在util.py顶部添加以下内容来检查这util.py

import sys
print(sys.path)

That's going to print out a list of all paths where the interpreter will look for modules.这将打印出解释器将在其中查找模块的所有路径的列表。 You'll see that only the path to the Parent module is there, because this is where the util.py was run from.您将看到只有Parent模块的路径在那里,因为这是util.py运行位置。 This is explained in The Module Search Path documentation:这在模块搜索路径文档中进行了解释:

When a module named spam is imported, the interpreter first searches for a built-in module with that name.当导入名为spam的模块时,解释器首先搜索具有该名称的内置模块。 If not found, it then searches for a file named spam.py in a list of directories given by the variable sys.path .如果未找到,它将在变量sys.path给出的目录列表中搜索名为spam.py的文件。 sys.path is initialized from these locations: sys.path从这些位置初始化:

  • The directory containing the input script (or the current directory when no file is specified).包含输入脚本的目录(或未指定文件时的当前目录)。
  • PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH ). PYTHONPATH (目录名称列表,语法与 shell 变量PATH )。
  • The installation-dependent default.依赖于安装的默认值。

When you run util.py from the Parent directory (= " The directory containing the input script "), and you do当您从父目录(=“包含输入脚本的目录”)运行util.py ,您会

from AReport import AReport

it will look for a AReport module from the Parent directory, but it's not there because only the report package is directly under the /path/to/Parent directory.它会从 Parent 目录中寻找AReport模块,但它不存在,因为只有report包直接在 /path/to/Parent 目录下。 That is why Python raises the ModuleNotFoundError .这就是 Python 引发ModuleNotFoundError If you do instead如果你这样做

from report.AReport import AReport

it's going to work because the report package is under /path/to/Parent.它会起作用,因为report包在 /path/to/Parent 下。

If you want to avoid the report.如果你想避免report. prefix when importing, one option is to add the report package to the sys.path on util.py :导入时添加前缀,一种选择是将report包添加到util.py上的sys.path

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

print(sys.path)
# should now show the /path/to/Parent/report on the list

Then your from AReport import will now work.然后你的from AReport导入现在可以工作了。 Another option is to add /path/to/Parent/report to your PYTHONPATH environment variable before running util.py .另一种选择是在运行util.py之前将 /path/to/Parent/report 添加到您的PYTHONPATH环境变量中。

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

I usually go with the PYTHONPATH option for tests, so that I don't need to modify the code.我通常使用PYTHONPATH选项进行测试,这样我就不需要修改代码。

尝试:

from report.AReport import AReport

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

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