【问题标题】:Correct way of "Absolute Import" in Python 2.7Python 2.7 中“绝对导入”的正确方法
【发布时间】:2015-11-24 12:21:06
【问题描述】:
  • Python 2.7.10
  • 在虚拟环境中
  • 在每个模块中启用from __future__ import absolute_import

目录树如下:

Project/
    prjt/
        __init__.py
        pkg1/
            __init__.py
            module1.py
            tests/
                __init__.py
                test_module1.py
        pkg2/
            __init__.py
            module2.py
            tests/
                __init__.py
                test_module2.py
        pkg3/
            __init__.py
            module3.py
            tests/
                __init__.py
                test_module3.py
    data/
    log/

我尝试在pkg1/module1.py 中使用compute() 的函数compute(),方法如下:

# In module1.py
import sys
sys.path.append('/path/to/Project/prjt')

from prjt.pkg2.module2 import compute

但是当我运行 python module1.py 时,解释器引发了 No module named prjt.pkg2.module2 的 ImportError。

  1. “绝对导入”的正确方式是什么?我必须将Project的路径添加到sys.path吗?
  2. 如何在交互式解释器中运行test_module1.py?通过python prjt/pkg1/tests/test_module1.pypython -m prjt/pkg1/tests/test_module1.py

【问题讨论】:

  • 是的,如果您在导入中引用项目,项目需要在路径上。否则只需from pkg2.module2... 等。
  • @DanielRoseman 谢谢。您能否说明“其他”情况?

标签: python python-2.7 python-import


【解决方案1】:

python如何查找模块

python 将从sys.path 中查找模块,sys.path[0] 的第一个条目是 '' 表示,python 将从当前工作目录中查找模块

import sys
print sys.path

和python从site-packages找到第三方模块

所以要绝对导入,可以

将您的包附加到sys.path

import sys
sys.path.append('the_folder_of_your_package')

import module_you_created

module_you_created.fun()

导出 PYTHONPATH

PYTHONPATH 将在执行前导入到 sys.path 中

export PYTHONPATH=the_folder_of_your_package

import sys
[p for p in sys.path if 'the_folder_of_your_package' in p]

如何在交互式解释器中运行 test_module1.py?通过 python Project/pkg1/tests/test_module1.py 还是 python -m Project/pkg1/tests/test_module1.py?

你可以使用if __name__ == '__main__':惯用的方式,使用python Project/pkg1/tests/test_module1.py

if __name__ = '__main__':
    main()

【讨论】:

  • 谢谢。我应该将sys.path.append('path/to/Project') 语句放在项目中的每个.py 文件中吗?或者只是将语句放在模块Project__init__.py 中?此外,我应该附加path/to/Project 还是path/to/Project/Project
  • 你可以把sys.path放到顶级包的__init__.py
  • 我将import syssys.path.append('/path/to/Project') 放在prjt/__init__.py 中。然后在终端cd /path/to/pkg1python module1.py中运行。但是引发了错误No module named prj.pkg2
  • 另一方面,我没有指定sys.path.append(),而是运行终端export PYTHONPATH="/path/to/Project",一切正常。所以我猜前面情况下的sys.path.append()语句没有运行。但我不想导出 bash 变量。你能帮我摆脱sys.path.append()的失败吗?
【解决方案2】:

如果将sys.path.append('path/to/Project') 添加到prjt/__init__.py 中,则需要导入子模块:from pkg2.module2 import compute(没有prjt 规范)因为prjt 包导入正在进行中,更高级别的文件夹不在@ 987654326@。这正是@Cissoid 所建议的。

顺便说一句,Py >= 3.0 不需要from __future__ import absolute_import


回答你的第二个问题...我的 unittests 子文件夹的结构非常相似,所以在 pkg/unittests/testall.py 我写了以下内容:

testfolder = os.path.abspath(os.path.dirname(__file__))
project_root = os.path.abspath(os.path.join(testfolder, r"..\.."))
sys.path.append(project_root)
import pkg

我在没有-m 选项的情况下运行它,因为它是不必要的复杂性。

【讨论】:

  • just : from __future__ import absolute_import 是不必要的,因为 python>=3.0,在此之前它仍然是必需的/制作差异。
  • 您需要根据@gst 的评论更正您的答案。它可能会误导人们。
【解决方案3】:

导入外部项目路径。

sys.path.append('/path/to/Project')

或从 pkg2 开始导入“计算”

from pkg2.module2 import compute

【讨论】:

    【解决方案4】:

    试试这个

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

    这将给出绝对路径

    【讨论】:

      【解决方案5】:

      使用显式相对导入,这应该可以从 module1.py 开始:

      from ..pkg2.module2 import compute()
      

      这比搞砸PYTHONPATH 更干净...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-04-08
        • 1970-01-01
        • 2011-04-06
        • 1970-01-01
        • 2011-04-29
        • 2015-09-13
        • 2013-02-27
        • 1970-01-01
        相关资源
        最近更新 更多