【问题标题】:Hide true modules隐藏真正的模块
【发布时间】:2014-11-20 04:02:07
【问题描述】:

主题是包导入和__init__ 文件: 规范中有一句话说

这些文件用于防止具有通用名称的目录 无意中隐藏了稍后出现在模块上的真实模块 搜索路径。如果没有这种保护措施,Python 可能会选择一个目录 这与您的代码无关,只是因为它看起来是嵌套的 在搜索路径上的较早目录中。

你能给我这方面的实际例子吗?

【问题讨论】:

    标签: python python-3.x module directory


    【解决方案1】:

    如果您允许将 any 目录视为一个包,那么尝试导入一个同时作为目录存在的模块 作为搜索路径上的模块可能选择模块上的目录。

    假设你有一个images 目录一个images.py 模块。 import images 会找到 images 目录,如果它在搜索路径上找到的话。

    通过要求__init__.py 来标记包,您可以在 Python 代码旁边包含此类数据目录,而不必担心掩盖具有相同名称的真正模块。

    【讨论】:

      【解决方案2】:

      当前Python documentation中没有这样的引用。

      PEP 420 Implicit Namespace Packages (Python 3.3+) specifies:

      • 如果找到<directory>/foo/__init__.py,则导入并返回常规包。
      • 如果没有,但找到<directory>/foo.{py,pyc,so,pyd},则导入并返回一个模块。扩展的确切列表因平台以及是否指定 -O 标志而异。此处的列表具有代表性。
      • 如果没有,但找到<directory>/foo 并且是一个目录,则记录它并继续扫描父路径中的下一个目录。
      • 否则扫描会继续父路径中的下一个目录。

      即,如果<directory>sys.path 中,那么import foo 可能对应于<directory>/foo,即使没有<directory>/foo/__init__.py。 pep 被接受,因此与拥有命名空间包的好处相比,由于偶然的import foo 成功而可能造成混淆的风险被认为太小了。

      除非您打算提供命名空间包,例如,为了让插件模块能够将它们放在不同的目录中(可作为不同的操作系统包安装),那么您应该始终为您的 Python 包提供__init__.py——显式优于隐含的。

      【讨论】:

      • 我尝试了@Martijn 示例,实际上“images”目录即使没有任何 init.py 文件也已导入,只是因为之前找到了它在搜索路径上。我以为只导入了包含 init.py 文件的目录。
      • @tt0686: 是的,如果sys.path 中没有images/__init__.pyimages.{py,pyc,...} 那么images 目录可以导致import images 成功:"如果<directory> 是在sys.path 然后import foo 可能对应于<directory>/foo,即使没有<directory>/foo/__init__.py"
      • 但是在没有任何语句或方法的情况下导入一些东西有什么意义呢?只是一个目录?
      • @tt0686: 阅读the rationale for pep 420 例如,“提供一个命名空间包,例如,插件模块能够将它们放在不同的目录中(可作为不同的操作系统包安装)”
      • 这意味着在以前的 Python 版本中(在命名空间包之前)没有 init.py 文件的目录不会被导入,对吗?
      猜你喜欢
      • 2015-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-30
      • 1970-01-01
      • 2015-09-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多