"from module import data; print(data)" vs "import module; print(module.data)"

Steven D'Aprano steve at pearwood.info
Thu Feb 25 19:40:31 EST 2016


On Fri, 26 Feb 2016 10:38 am, Ben Finney wrote:

> Gregory Ewing <greg.ewing at canterbury.ac.nz> writes:
> 
>> sohcahtoa82 at gmail.com wrote:
>> > Now, I've noticed people talking about importing os.path.  Is there any
>> > reason to use "import os.path" rather than "import os"?  Both of them
>> > will still put the "os" module into the global namespace.
>>
>> In the case of os.path it doesn't matter, because the
>> os module imports the appropriate path module automatically.
> 
> My position is that behaviour violates one of the principles of the Zen
> of Python: “Special cases aren't special enough to break the rules.”


But it's not special. It's the standard behaviour of any module which offers
a public name: `import os` makes all the names in the os name space
available. There's no difference between (say) `os.listdir` and `os.path`
except that listdir happens to be a function and path happens to be a
module.

`path` has been a documented public attribute of the `os` module since at
least Python 1.5:

[steve at ando ~]$ python1.5 -c "import os; print os.path"
<module 'posixpath' from '/usr/local/lib/python1.5/posixpath.pyc'>


and likely older. The documentation from help(os) says:

DESCRIPTION
    This exports:
      - all functions from posix, nt, os2, mac, or ce, e.g. unlink, 
        stat, etc.
      - os.path is one of the modules posixpath, ntpath, or macpath

(The above is from 2.4, the oldest Python I have that supports docstrings;
in 3.3 it is substantially the same except macpath is removed.)


Since `os` is not a package, the fact that importing `os.path` works at all
is surprising. The os module has to make a special effort to support
importing os.path. From the source code:

sys.modules['os.path'] = path

If you take "Special cases are not special enough" seriously, you will not
use `import os.path` since os is not a package:

py> os.__package__
''

and os.path is not part of os, it's just a publicly exposed attribute which
merely happens to be a module. Being a module doesn't make it special, it's
just another name in the os namespace. I trust that you wouldn't insist on
writing:

import os.listdir

(especially since that doesn't work). Neither should you insist on writing
`import os.path`, since path is documented as a public part of the os
module. It has done so since at least Python 1.5.


>> But in general, importing a package won't necessarily
>> import submodules under it, so sometimes you need to
>> import somepackage.somemodule explicitly.
> 
> Because that's normally the case, I choose not to rely on that special
> behaviour of ‘os’. If I need ‘os.path’, I import it explicitly so no
> reader needs to guess::
> 
>     import os
>     import os.path

As I have shown above, the fact that os.path is importable at all is the
special case.



-- 
Steven



More information about the Python-list mailing list