Python Imports,Paths,Directories&模块

时间:2011-08-23 15:05:09

标签: python module package

首先让我说我已经对过去一周的课程进行了广泛的研究,但还没有找到这些问题的实际答案 - 只是一些模糊的答案并没有真正解释正在发生的事情。如果这只是因为我错过了我想要的东西,我很抱歉 - 请指出我正确的方向。

我的目录结构是:

TestProject/
    runtest*
    testpackage/
        __init__.py
        testmod.py
        testmod2.py
        testsubs/
            testsubmod.py

一对夫妇注意到:

  • 我在Ubuntu上使用python2.7
  • 我正在使用bpython
  • 进行测试
  • 我正在从特定目录运行bpython来测试导入行为的方式
  • 我正在尝试遵循最佳做法。
  • 此软件包未安装,它位于随机开发目录
  • 此目录不在pythonpath
  • 我在程序包目录中有一个 init .py
  • 嵌套目录中没有 init .py文件
  • init .py文件为空
  • testpackage / testmod.py包含TestModClass
  • testpackage / testsubs / testsubmod.py包含TestSubModClass

我观察过的事情:

  • 当我从TestProject / 导入testpackage 运行bpython时
    • 这不会导入testpackage.testmod
    • 我无法访问testpackage.testmod
  • 当我从TestProject运行bpython时, import testpackage.testmod 失败
  • 当我从testProject运行bpython /从testpackage导入testmod
  • 我可以将代码添加到 init .py以显式导入testmod.py,但不能testubs / testmod.py
    • 我不认为这是正确的方法,如果用户不想导入该模块怎么办?
  • 从testmod.py
  • 我可以导入testmod2,但不能导入testpackage.testmod2
    • 这样做很好,我可以使用STL或者扭曲的名称(例如testpackage.logging)来命名我自己的模块,而不会导致错误(很难将自己的模块命名为客户日志,而不是只是mypackage.logging)

问题:

  1. python是否与包装上的导入有所不同? pythonpath中存在的模块比尝试从当前目录导入模块时要好吗?
  2. 为什么不导入testpackage让我访问testpackage.testmod?当我导入os时,我可以访问os.path(etc)。
  3. 使用软件包,我应该坚持在基本目录中使用单个 init .py,还是应该将它们嵌套在后续目录中?
  4. 如何导入指定包名称的模块? I.E.从testmod.py,我想导入testpackage.testmod2,而不仅仅是testmod2。
  5. 从subsubs目录导入子模块的正确方法是什么?
    1. 我看到的唯一解决方案是将该目录从 init .py附加到pythonpath,但我不知道这是否正确。
  6. 提前致谢。

2 个答案:

答案 0 :(得分:8)

首先,您会在section 6 of The Python Tutorial找到所需的所有信息。


  

(1)python是否与包装上的进口有不同的处理& pythonpath中存在的模块比尝试从当前目录导入模块时要好吗?

不,它没有。实际上,Python在导入模块时总是搜索sys.path。仅找到当前目录中的模块,因为sys.path包含带有空字符串的条目,表示当前目录。


  

(2)为什么import testpackage不允许我访问testpackage.testmod?当我导入os时,我可以访问os.path(等)。

为提高效率,import testpackage仅加载testpackage/__init__.py。如果您需要testpackage.testmod,则必须明确导入它:

import testpackage   # Just imports testpackage, not testpackage.testmod!
import testpackage.testmod   # Import *both* testpackage and testpackage.testmod!

如果您始终要导出testmod,请在__init__.py内导出,这是osos/__init__.py)的作用。这样,如果您导入testpackage.testmod,则testpackage始终可以隐含使用。

由于Python是跨平台的,因此实际上无法在目录中一致地自动加载模块,因为某些文件系统不区分大小写(Windows!)。 Python不知道是否将os/path.py加载为os.pathos.Path等。


  

(3)对于一个包,我应该坚持在基目录中使用单个__init__.py,还是应该将它们嵌套在后续目录中?

每个子包总是需要__init__.py。有关于放弃这一要求的讨论,但决定保持原样。


  

(4)如何导入指定包名称的模块? I.E.来自testmod.py,我想导入testpackage.testmod2而非testmod2

这应该有效。只需确保从顶级目录运行代码。如果当前目录为testpackage,则testmod不知道它在包中。

首选方法是使用相对的包内导入:

from . import testmod2

如果存在名为testmod2的全局模块,则可以防止名称冲突,并且可以使用包中的已知模块的名称而不会出现问题。


  

(5)从subsubs目录导入子模块的正确方法是什么?   我看到的唯一解决方案是将该目录从__init__.py附加到pythonpath,但我不知道这是否正确。

不,不要那样做!当其中一个父目录已经在sys.path时,永远不要将目录放到sys.path!这可能导致你的模块被加载两次,这是一件坏事!

通常您应该能够使用绝对或相对导入从子包加载模块:

import testpackage.testsubs.testsubmod
from testpackage.testsubs import testsubmod
from .testsubs import testsubmod

确保在__init__.py内创建testsubs/

答案 1 :(得分:0)

  1. 否。当前目录刚刚添加到PYTHONPATH。
  2. 首先,你需要一个__init__.py。其次,os.path是因为os正在导入os.path。
  3. 每个目录中都需要__init__.py,也包含testpackage目录。
  4. 在包的__init__.py中,导入您要提供的模块。
  5. 来自sub1.sub2 import子模块的
    1. 不,如果最顶层的目录在PYTHONPATH上,并且这个和子目录都有__init__.py,那么这就是从任何子目录导入的全部内容。