基本 Python 导入机制

Basic Python import mechanics

我有以下目录树:

project/
  A/
    __init__.py
    foo.py
  TestA/
    __init__.py
    testFoo.py

testFoo 的内容是:

import unittest
from A import foo

来自 project 目录我 运行 python testA/testFoo.py

我得到一个ModuleNotFoundError No module named A

我有两个问题:如何从 TestA.testFoo 导入和 运行 A.foo 以及为什么 Python 中的导入逻辑如此难以理解?有没有什么调试技巧可以快速解决这类问题,很抱歉我不得不用这些基本问题来打扰你?

首先将文件夹project/testA添加到系统pythonpath中:

import sys
sys.path.insert(0, "/path/to/pythonfile")

然后再次尝试导入。

当你执行一个文件时,会生成一个名为pythonpath的环境变量,pythonimport使用这个变量来找到你要导入的文件,这个路径是用你正在执行的文件,它将在当前目录和包含 __init__.py 文件的子目录中搜索,如果你想从同一级别的目录导入,你需要修改你的 python 路径或更改项目的体系结构,因此执行的文件始终位于顶层。

您可以像这样包含您的 python 路径:

import sys
sys.path.insert(0, "/path/to/file.py")

您可以阅读有关导入系统的更多信息:https://docs.python.org/3/reference/import.html

我认为最好的方法是不要触及 python 路径并将您的测试目录包含到测试文件所在的目录中:

project/
  A/
    __init__.py
    foo.py
    TestA/
        __init__.py
        testFoo.py

然后运行将python -m unittest命令放入你的A或项目目录,它会搜索你的当前目录和子目录进行测试并执行它。

更多关于单元测试的信息:https://docs.python.org/3/library/unittest.html

你能试试这个吗?

在子目录 TestA 中创建一个空文件 __init__.py。并在主代码的开头添加

from __future__ import absolute_import

然后导入如下:

import A.foo as testfoo

py3中推荐的方式可能如下所示

echo $pwd
$ /home/user/project
python -m testA.testFoo

在python中执行模块python -m的方式是替换相对引用的好方法。

您肯定找不到 A,因为 python 需要从 sys.pathPYTHONPATH 查找模块。

并且 python 会自动将当前 top level script 添加到 sys.path 而不是 currently directorysys.path。因此,如果您在 testFoo.py 中添加 print(sys.path),您将看到它只会将 project/TestA 添加到 sys.path

换句话说,project没有被包含在sys.path中,那么python如何找到模块A

所以你必须自己将 project 文件夹添加到 sys.path,而且,这只是 top script 中需要的,如下所示:

import unittest
import sys
import os
file_path = os.path.abspath(os.path.dirname(__file__)).replace('\', '/')
lib_path = os.path.abspath(os.path.join(file_path, '..')).replace('\', '/')
sys.path.append(lib_path)