根据official documentation,os.path
是一个模块。那么,导入它的首选方式是什么?
# Should I always import it explicitly?
import os.path
或者...
# Is importing os enough?
import os
请不要回答“导入os
为我工作”。我知道,它现在也适用于我(从Python 2.6开始)。我想知道的是关于这个问题的任何官方建议。因此,如果您回答此问题,请发布您的推荐信息。
答案 0 :(得分:143)
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项目采用这种方法,这往往会产生更多结构化代码。
答案 1 :(得分:29)
根据Tim Peters的PEP-20,“明确比隐含更好”和“可读性计数”。如果os
模块中的所有内容都位于os.path
下,则import os.path
会更明确,让其他人知道您真正关心的内容。
同样,PEP-20也说“简单比复杂更好”,所以如果你还需要更常规的os
伞下的东西,import os
将是首选。
答案 2 :(得分:15)
明确答案: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).
...
答案 3 :(得分:6)
有趣的是,导入os.path会导入所有操作系统。在交互式提示中尝试以下操作:
import os.path
dir(os)
结果与刚刚导入的os相同。这是因为os.path将根据您拥有的操作系统引用不同的模块,因此python将导入os以确定要为路径加载哪个模块。
对于某些模块,说import foo
不会公开foo.bar
,所以我想这实际上取决于特定模块的设计。
通常,只需导入所需的显式模块应该稍微快一点。在我的机器上:
import os.path
: 7.54285810068e-06
秒
import os
: 9.21904878972e-06
秒
这些时间足够接近,可以忽略不计。您的程序可能需要现在或稍后使用os
中的其他模块,因此通常只需牺牲两微秒并使用import os
来避免以后出现此错误。我通常只是将os整体导入,但可以看出为什么有些人会更喜欢import os.path
在技术上更高效,并向代码的读者传达这是os
模块的唯一部分需要使用。它基本上归结为我脑海中的一个风格问题。
答案 4 :(得分:4)
找不到任何明确的引用,但我看到os.walk的示例代码使用os.path但只导入os
答案 5 :(得分:3)
常识在这里起作用:os
是一个模块,os.path
也是一个模块。因此,只需导入要使用的模块即可:
如果要在os
模块中使用功能,请导入os
。
如果要在os.path
模块中使用功能,请导入os.path
。
如果要在两个模块中使用功能,请导入两个模块:
import os
import os.path
供参考:
Lib/idlelib/rpc.py使用os
并导入os
。
Lib/idlelib/idle.py使用os.path
并导入os.path
。
Lib/ensurepip/init.py同时使用和导入。
答案 6 :(得分:-1)
我同意Mike的意见
我认为
import os
没问题。
然后你必须提到这样的细节
os.path()
或者如果您正在调用模块中的模块
os.path.exists()