Should I use `import os.path` or `import os`?
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 insys.modules
.
os
is among the modules that are loaded when Python starts up. It assigns itspath
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
If you think of
os
as a package and know that you can doimport os
and have access to the submoduleos.path
, you may be surprised later when you can't doimport twisted
and automatically accesstwisted.spread
without importing it.It is confusing that
os.name
is a normal thing, a string, andos.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.
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.
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 tothis module as os.path. The "os.path" name is an alias for thismodule on Posix systems; on other systems (e.g. Mac, Windows),os.path provides the same operations in a manner specific to thatplatform, and is an alias to another module (e.g. macpath, ntpath)....