我应该使用‘ import os.path’还是‘ import os’?

根据 正式文件os.path是一个模块。因此,导入它的首选方法是什么?

# Should I always import it explicitly?
import os.path

或者..。

# Is importing os enough?
import os

请不要回答“进口 os为我工作”。我知道,它现在对我也适用(对于 Python 2.6)。我想知道的是关于这个问题的任何官方建议。所以,如果你回答这个问题,请 公布你的推荐信

122513 次浏览

有趣的是,导入 os.path 会导入所有的 os.try 在交互式提示符下:

import os.path
dir(os)

结果将与您刚刚导入的操作系统相同。这是因为 os.path 将引用一个不同的模块,这个模块基于您所使用的操作系统,所以 python 将导入 os 来确定要为 path 加载哪个模块。

参考文献

对于一些模块,说 import foo不会暴露 foo.bar,所以我想这真的取决于具体模块的设计。


一般来说,只需要导入所需的显式模块就会稍微快一些:

1秒

1秒

这些时间非常接近,可以忽略不计。您的程序可能需要现在或以后使用来自 os的其他模块,因此通常只需牺牲两微秒并使用 import os以避免以后出现此错误就可以了。我通常支持将 OS 作为一个整体导入,但是可以理解为什么有些人希望 import os.path在技术上更加高效,并且向代码读者传达这是 os模块中唯一需要使用的部分。这基本上可以归结为我心目中的一个时尚问题。

找不到任何明确的引用,但我看到 Os. 走的示例代码使用 os.path,但只导入 os

根据 Tim Peters 的 PEP-20,“显性比隐性好”和“可读性很重要”。如果您所需要的 os模块都在 os.path之下,那么 import os.path将更加明确,并让其他人知道您真正关心的是什么。

同样地,PEP-20也说“简单比复杂好”,所以如果你还需要更一般的 os保护伞下的东西,import os将是首选。

os.path的工作方式很有趣。看起来 os应该是一个包含子模块 path的包,但实际上 os是一个普通模块,它可以神奇地用 sys.modules注入 os.path。事情是这样的:

  • 当 Python 启动时,它将大量模块加载到 sys.modules中。它们不绑定到脚本中的任何名称,但是当您以某种方式导入它们时,可以访问已经创建的模块。

    • sys.modules是一个模块缓存在其中的告示。当您导入一个模块时,如果它已经被导入到某个地方,那么它将获取存储在 sys.modules中的实例。
  • os是 Python 启动时加载的模块之一。它将其 path属性分配给特定于 OS 的路径模块。

  • 它注入 sys.modules['os.path'] = path,这样你就可以像做一个子模块一样做“ import os.path”。

我倾向于认为 os.path我想用的模块而不是 os模块里的东西,所以即使它不是 真的,也不是 os的子模块,我把它导入到 os我总是做 import os.path中。这与 os.path文档化的方式是一致的。


顺便说一句,我认为这种结构导致了许多 Python 程序员早期对模块、包和代码组织的困惑。这其实有两个原因

  1. 如果您将 os视为一个包,并且知道您可以执行 import os并访问子模块 os.path,那么以后您可能会感到惊讶,因为您不能执行 import twisted并自动访问 twisted.spread而不导入它。

  2. 令人困惑的是,os.name是一个普通的东西,一个字符串,而 os.path是一个模块。我总是用空的 __init__.py文件来构造我的包,这样在同一层次上我总是有一种类型的东西: 模块/包或其他东西。一些大型的 Python 项目采用这种方法,这种方法倾向于产生更结构化的代码。

决定性答案: import os和使用 os.path。不要直接 import os.path

根据模块本身的文档:

>>> import os
>>> help(os.path)
...
Instead of importing this module directly, import os and refer to
this module as os.path.  The "os.path" name is an alias for this
module on Posix systems; on other systems (e.g. Mac, Windows),
os.path provides the same operations in a manner specific to that
platform, and is an alias to another module (e.g. macpath, ntpath).
...

常识在这里起作用: os是一个模块,而 os.path也是一个模块。所以只要导入想要使用的模块:

  • 如果您想在 os模块中使用功能,那么导入 os

  • 如果您想在 os.path模块中使用功能,那么导入 os.path

  • 如果希望在两个模块中都使用功能,那么导入两个模块:

    import os
    import os.path
    

For reference: