317

这是我第一次真正坐下来尝试 python 3,但似乎失败得很惨。我有以下两个文件:

  1. 测试.py
  2. 配置文件

config.py 中定义了一些函数以及一些变量。我已将其简化为以下内容:

配置文件

debug = True

测试.py

import config
print (config.debug)

我也有一个__init__.py

但是,我收到以下错误:

ModuleNotFoundError: No module named 'config'

我知道 py3 约定是使用绝对导入:

from . import config

但是,这会导致以下错误:

ImportError: cannot import name 'config'

所以我不知道在这里做什么......非常感谢任何帮助。:)

4

16 回答 16

265

TL;DR:您不能从您执行的文件中进行相对导入,因为__main__模块不是包的一部分。

绝对进口- 进口可用的东西sys.path

相对导入- 导入与当前模块相关的东西,必须是包的一部分

如果您以完全相同的方式运行这两个变体,则其中一个应该可以工作。这是一个示例,可以帮助您了解正在发生的事情。让我们添加另一个main.py具有如下整体目录结构的文件:

.
./main.py
./ryan/__init__.py
./ryan/config.py
./ryan/test.py

让我们更新test.py看看发生了什么:

# config.py
debug = True
# test.py
print(__name__)

try:
    # Trying to find module in the parent package
    from . import config
    print(config.debug)
    del config
except ImportError:
    print('Relative import failed')

try:
    # Trying to find module on sys.path
    import config
    print(config.debug)
except ModuleNotFoundError:
    print('Absolute import failed')
# main.py
import ryan.test

我们test.py先运行:

$ python ryan/test.py
__main__
Relative import failed
True

这里的“test”模块,对__main__属于包一无所知。但是import config应该可以工作,因为该ryan文件夹将被添加到sys.path.

让我们运行main.py

$ python main.py
ryan.test
True
Absolute import failed

这里的 test 位于“ryan”包中,可以执行相对导入。import config失败,因为 Python 3 中不允许隐式相对导入。

希望这有帮助。

PS:如果您坚持使用 Python 3,则不再需要__init__.py文件。

于 2017-05-09T02:12:25.683 回答
101

我想到了。非常令人沮丧,尤其是来自python2。

.无论它是相对的还是绝对的,您都必须将 a 添加到模块中。

我按如下方式创建了目录设置。

/main.py
--/lib
  --/__init__.py
  --/mody.py
  --/modx.py

修改文件

def does_something():
    return "I gave you this string."

模块.py

from modx import does_something

def loaded():
    string = does_something()
    print(string)

主文件

from lib import mody

mody.loaded()

当我执行 main 时,会发生这种情况

$ python main.py
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    from lib import mody
  File "/mnt/c/Users/Austin/Dropbox/Source/Python/virtualenviron/mock/package/lib/mody.py", line 1, in <module>
    from modx import does_something
ImportError: No module named 'modx'

我跑了2to3,核心输出是这个

RefactoringTool: Refactored lib/mody.py
--- lib/mody.py (original)
+++ lib/mody.py (refactored)
@@ -1,4 +1,4 @@
-from modx import does_something
+from .modx import does_something

 def loaded():
     string = does_something()
RefactoringTool: Files that need to be modified:
RefactoringTool: lib/modx.py
RefactoringTool: lib/mody.py

我不得不修改 mod.py 的 import 语句来修复它

try:
    from modx import does_something
except ImportError:
    from .modx import does_something


def loaded():
    string = does_something()
    print(string)

然后我再次运行 main.py 并得到了预期的输出

$ python main.py
I gave you this string.

最后,只是为了清理它并使其在 2 和 3 之间可移植。

from __future__ import absolute_import
from .modx import does_something
于 2017-08-07T21:32:48.860 回答
92

您必须将项目的路径附加到PYTHONPATH并确保使用绝对导入


对于 UNIX(Linux、OSX、...)

export PYTHONPATH="${PYTHONPATH}:/path/to/your/project/"

对于 Windows

set PYTHONPATH=%PYTHONPATH%;C:\path\to\your\project\

绝对进口

假设我们有以下项目结构,

└── myproject
    ├── mypackage
    │   ├── __init__.py
    │   ├── a.py
    └── anotherpackage
        ├── __init__.py
        ├── b.py
        ├── c.py
        └── mysubpackage
            ├── __init__.py
            └── d.py

只需确保从项目的根目录开始引用每个导入。例如,

# in module a.py
import anotherpackage.mysubpackage.d

# in module b
import anotherpackage.c
import mypackage.a

有关更全面的解释,请参阅文章如何修复 ModuleNotFoundError 和 ImportError

于 2019-07-23T12:53:49.907 回答
54

设置 PYTHONPATH 也可以帮助解决这个问题。

这是如何在 Windows 上完成的

set PYTHONPATH=.

于 2018-02-02T04:51:26.283 回答
20

您可以简单地将以下文件添加到您的测试目录中,然后 python 将在测试之前运行它

__init__.py file

import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
于 2019-04-22T13:28:00.940 回答
15

试过你的例子

from . import config

得到以下 SystemError:
/usr/bin/python3.4 test.py
Traceback (最近一次调用最后):
File "test.py", line 1, in
from . 导入配置
系统错误:父模块''未加载,无法执行相对导入


这对我有用:

import config
print('debug=%s'%config.debug)

>>>debug=True

用 Python 测试:3.4.2 - PyCharm 2016.3.2


除了这个 PyCharm 还提供了Import this name
您必须单击config并出现帮助图标在此处输入图像描述

于 2017-05-05T08:35:10.497 回答
14

PYTHONPATH在根项目目录中设置环境变量。

考虑类 UNIX:

export PYTHONPATH=.
于 2020-02-17T13:55:33.243 回答
9

在调用模块之前声明正确的sys.path列表:

import os, sys

#'/home/user/example/parent/child'
current_path = os.path.abspath('.')

#'/home/user/example/parent'
parent_path = os.path.dirname(current_path)

sys.path.append(parent_path)
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'child.settings')
于 2019-04-09T16:55:56.433 回答
7

如果您使用的是 python 3+,请尝试添加以下行

import os, sys
dir_path = os.path.dirname(os.path.realpath(__file__))
parent_dir_path = os.path.abspath(os.path.join(dir_path, os.pardir))
sys.path.insert(0, parent_dir_path)
于 2020-05-24T16:12:34.843 回答
4

此示例适用于 Python 3.6。

我建议进入Run -> Edit ConfigurationsPyCharm,删除那里的所有条目,然后尝试再次通过 PyCharm 运行代码。

如果这不起作用,请检查您的项目解释器(设置 -> 项目解释器)并运行配置默认值(运行 -> 编辑配置...)。

于 2017-05-11T21:27:19.950 回答
4

尝试

from . import config

这样做是从同一文件夹级别导入。如果您直接尝试导入它假定它是从属

于 2020-05-18T03:27:48.417 回答
3

正如对原始帖子的评论中所述,无论出于何种原因,这似乎是我使用的 python 解释器的问题,而不是 python 脚本的问题。我从 python.org 从 WinPython 包切换到官方 python 3.6,它工作得很好。感谢大家的帮助:)

于 2017-05-12T13:30:50.813 回答
3

我在一台 Linux 机器上工作。我跑步时遇到了同样的问题python my_module/__main__.py

export PYTHONPATH=.如果在运行脚本之前运行命令,则错误已修复。

export PYTHONPATH=.
python my_module/__main__.py
于 2021-10-28T09:23:32.730 回答
2

对我来说,只需添加当前目录即可。

使用以下结构:

└── myproject
    ├── a.py
    └── b.py

一个.py:

from b import some_object
# returns ModuleNotFound error

from myproject.b import some_object
# works
于 2020-12-10T11:50:03.287 回答
0

您可以使用这些语句来设置对我有用的工作目录python3

import os
import sys
sys.path.insert(1, os.getcwd())
于 2022-02-09T22:51:32.437 回答
0

根据我的经验,PYTHONPATH 环境变量并非每次都有效。

就我而言,我的 pytest 仅在我添加绝对路径时才有效: sys.path.insert( 0, "/Users/bob/project/repo/lambda" )

于 2022-02-10T15:01:41.893 回答