我应该使用`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的情况下)。我想知道的是关于这个问题的任何官方建议。所以,如果你回答这个问题,请提供你的参考资料。
6 个回答
明确的答案是:使用 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).
...
根据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
属性指向一个特定于操作系统的路径模块。它通过
sys.modules['os.path'] = path
的方式,让你能够像使用子模块一样使用 "import os.path
"。
我通常把 os.path
看作是 我想用的一个模块,而不是 在 os
模块中的一个东西。所以尽管它并不是真正的 os
包的子模块,我还是像使用子模块一样导入它,并且我总是使用 import os.path
。这和 os.path
的文档说明是一致的。
顺便提一下,这种结构让很多初学 Python 的程序员在模块、包和代码组织方面感到困惑,我觉得主要有两个原因:
如果你把
os
当作一个包,并知道你可以通过import os
来访问子模块os.path
,那么当你发现不能通过import twisted
自动访问twisted.spread
时,可能会感到惊讶。还有一点让人困惑的是,
os.name
是一个普通的字符串,而os.path
是一个模块。我总是用空的__init__.py
文件来组织我的包,这样在同一层级上我总是有一种类型的东西:模块/包或其他东西。许多大型 Python 项目也采取这种方法,这样代码结构会更清晰。