相对导入 - ModuleNotFoundError:没有名为x的模块

时间:2017-05-02 00:40:42

标签: python python-3.x package python-import relative-import

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

  1. test.py
  2. config.py
  3. config.py中定义了一些函数以及一些变量。我已将其剥离到以下内容:

    enter image description here

    但是,我收到以下错误:

    ModuleNotFoundError: No module named 'config'
    

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

    from . import config
    

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

    ImportError: cannot import name 'config'
    

    所以我不知道该怎么做......非常感谢任何帮助。 :)

13 个答案:

答案 0 :(得分:88)

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

此处测试是在“ryan”包中,可以执行相对导入。 import config失败,因为Python 3中不允许隐式相对导入。

希望这会有所帮助。

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

答案 1 :(得分:34)

我明白了。非常令人沮丧,特别是来自python2。

您必须向模块添加.,无论它是相对的还是绝对的。

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

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

modx.py

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

mody.py

from modx import does_something

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

main.py

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'

我跑了2到3,核心输出就是这个

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

我必须修改mody.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

答案 2 :(得分:17)

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

以下是在Windows上完成的方法

set PYTHONPATH=.

答案 3 :(得分:9)

试过你的例子

from . import config
  

得到以下SystemError:
  /usr/bin/python3.4 test.py
  追溯(最近的呼叫最后):
    文件“test.py”,第1行,在       来自。 import config
   SystemError:未加载父模块,无法执行相对导入

这对我有用:

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

>>>debug=True

使用Python测试:3.4.2 - PyCharm 2016.3.2

除此之外,PyCharm还为您提供导入此名称 您可以点击config,然后会出现帮助图标enter image description here

答案 4 :(得分:8)

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

考虑类UNIX:

export PYTHONPATH=.

答案 5 :(得分:2)

您只需将以下文件添加到测试目录中,然后python将在测试之前运行该文件

__init__.py file

import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

答案 6 :(得分:1)

如果您使用的是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)

答案 7 :(得分:0)

正如原帖的评论中所述,这似乎是我用于任何原因的python解释器的一个问题,而不是python脚本的错误。我从WinPython包切换到python.org上的官方python 3.6,它运行得很好。感谢大家的帮助:)。

答案 8 :(得分:0)

在调用模块之前声明正确的 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')

答案 9 :(得分:0)

您必须将路径追加到PYTHONPATH中的模块:

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

答案 10 :(得分:0)

尝试

from . import config

该操作是从同一文件夹级别导入的。如果您直接尝试导入,则假定它是下属

答案 11 :(得分:0)

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

使用以下结构:

$ unset v
$ for f in a A i l n r t u x; do declare -$f v; echo "$f: ${v@a}"; done
a: a
bash: declare: v: cannot convert indexed to associative array
A: a
i: ai
l: ail
bash: declare: v: reference variable cannot be an array
n: ail
r: airl
t: airtl
u: airtu
x: airtxu
$

a.py:

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

答案 12 :(得分:-1)

pip install config

显然我不能只输入 18 个字符,因此这个文本!