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

问题:我应该使用`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起)。我想知道的是有关此问题的任何官方建议。因此,如果您回答这个问题,请发表您的参考资料

According to the official documentation, os.path is a module. Thus, what is the preferred way of importing it?

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

Or…

# Is importing os enough?
import os

Please DON’T answer “importing os works for me”. I know, it works for me too right now (as of Python 2.6). What I want to know is any official recommendation about this issue. So, if you answer this question, please post your references.


回答 0

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,我也可以像导入一个一样来导入它,并且我总是这样做import os.path。这与os.path记录方式一致。


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

  1. 如果您将其os视为一个包并且知道可以执行import os并有权访问该子模块os.path,则稍后可能会感到惊讶,因为您无法执行import twisted并且twisted.spread无需导入即可自动访问。

  2. 令人困惑的是,这os.name是正常现象,字符串和os.path模块。我总是用空__init__.py文件来构造我的包,以便在同一级别上我总是有一种类型的东西:模块/包或其他东西。几个大型的Python项目都采用这种方法,这往往会使代码更加结构化。

os.path works in a funny way. It looks like os should be a package with a submodule path, but in reality os is a normal module that does magic with sys.modules to inject os.path. Here’s what happens:

  • When Python starts up, it loads a bunch of modules into sys.modules. They aren’t bound to any names in your script, but you can access the already-created modules when you import them in some way.

    • sys.modules is a dict in which modules are cached. When you import a module, if it already has been imported somewhere, it gets the instance stored in sys.modules.
  • os is among the modules that are loaded when Python starts up. It assigns its path attribute to an os-specific path module.

  • It injects sys.modules['os.path'] = path so that you’re able to do “import os.path” as though it was a submodule.

I tend to think of os.path as a module I want to use rather than a thing in the os module, so even though it’s not really a submodule of a package called os, I import it sort of like it is one and I always do import os.path. This is consistent with how os.path is documented.


Incidentally, this sort of structure leads to a lot of Python programmers’ early confusion about modules and packages and code organization, I think. This is really for two reasons

  1. If you think of os as a package and know that you can do import os and have access to the submodule os.path, you may be surprised later when you can’t do import twisted and automatically access twisted.spread without importing it.

  2. It is confusing that os.name is a normal thing, a string, and os.path is a module. I always structure my packages with empty __init__.py files so that at the same level I always have one type of thing: a module/package or other stuff. Several big Python projects take this approach, which tends to make more structured code.


回答 1

根据蒂姆·彼得斯(Tim Peters)撰写的PEP-20,“显式胜于隐式”和“可读性”。如果您需要从os模块中获得的全部在之下os.pathimport os.path则会更加明确,并让其他人知道您真正关心的是什么。

同样,PEP-20也说“简单胜于复杂”,因此,如果您还需要一些更笼统的资料osimport os则首选。

As per PEP-20 by Tim Peters, “Explicit is better than implicit” and “Readability counts”. If all you need from the os module is under os.path, import os.path would be more explicit and let others know what you really care about.

Likewise, PEP-20 also says “Simple is better than complex”, so if you also need stuff that resides under the more-general os umbrella, import os would be preferred.


回答 2

最终答案: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).
...

Definitive answer: import os and use os.path. do not import os.path directly.

From the documentation of the module itself:

>>> 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

有趣的是,导入os.path将导入所有os。在交互式提示中尝试以下操作:

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需要使用的模块的唯一部分。在我看来,它本质上可以归结为样式问题。

Interestingly enough, importing os.path will import all of os. try the following in the interactive prompt:

import os.path
dir(os)

The result will be the same as if you just imported os. This is because os.path will refer to a different module based on which operating system you have, so python will import os to determine which module to load for path.

reference

With some modules, saying import foo will not expose foo.bar, so I guess it really depends the design of the specific module.


In general, just importing the explicit modules you need should be marginally faster. On my machine:

import os.path: 7.54285810068e-06 seconds

import os: 9.21904878972e-06 seconds

These times are close enough to be fairly negligible. Your program may need to use other modules from os either now or at a later time, so usually it makes sense just to sacrifice the two microseconds and use import os to avoid this error at a later time. I usually side with just importing os as a whole, but can see why some would prefer import os.path to technically be more efficient and convey to readers of the code that that is the only part of the os module that will need to be used. It essentially boils down to a style question in my mind.


回答 4

常识在这里起作用:os是模块,os.path也是模块。因此,只需导入要使用的模块:

  • 如果要在os模块中使用功能,请导入os

  • 如果要在os.path模块中使用功能,请导入os.path

  • 如果要在两个模块中使用功能,则导入两个模块:

    import os
    import os.path

以供参考:

Common sense works here: os is a module, and os.path is a module, too. So just import the module you want to use:

  • If you want to use functionalities in the os module, then import os.

  • If you want to use functionalities in the os.path module, then import os.path.

  • If you want to use functionalities in both modules, then import both modules:

    import os
    import os.path
    

For reference:


回答 5

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

Couldn’t find any definitive reference, but I see that the example code for os.walk uses os.path but only imports os