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

164 投票
6 回答
131094 浏览
提问于 2025-04-15 22:05

根据官方文档os.path是一个模块。那么,导入它的最佳方式是什么呢?

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

或者……

# Is importing os enough?
import os

请不要回答“导入os对我来说没问题”。我知道,这对我来说也没问题(在Python 2.6的情况下)。我想知道的是关于这个问题的任何官方建议。所以,如果你回答这个问题,请提供你的参考资料

6 个回答

17

明确的答案是:使用 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).
...
31

根据Tim Peters的PEP-20,有几个原则很重要:“明确比含糊好”和“可读性很重要”。如果你只需要使用os模块下的os.path,那么直接写import os.path会更清楚,这样别人一看就知道你关注的是什么。

同样,PEP-20还提到“简单比复杂好”,所以如果你还需要用到os模块下的其他内容,直接写import os会更合适。

190

os.path 的工作方式有点特别。表面上看,os 应该是一个包含子模块 path 的包,但实际上 os 只是一个普通的模块,它通过一些魔法操作 sys.modules 来让你能使用 os.path。具体发生了什么呢:

  • 当 Python 启动时,它会把一堆模块加载到 sys.modules 中。这些模块在你的脚本中并没有绑定到任何名字,但你可以通过某种方式导入它们来访问这些已经创建的模块。

    • sys.modules 是一个字典,用来缓存模块。当你导入一个模块时,如果这个模块之前已经被导入过,它就会获取到存储在 sys.modules 中的实例。
  • os 是 Python 启动时加载的模块之一。它把自己的 path 属性指向一个特定于操作系统的路径模块。

  • 它通过 sys.modules['os.path'] = path 的方式,让你能够像使用子模块一样使用 "import os.path"。

我通常把 os.path 看作是 我想用的一个模块,而不是 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 项目也采取这种方法,这样代码结构会更清晰。

撰写回答