I have observed the following behavior in python 3.4.2, and I am unableto explain it. Hopefully someone could shed some light on the matter:
In IPython:
In [129]: import urllib
In [130]: print(urllib.parse)
<module 'urllib.parse' from '/Users/ashwin/.pyenv/versions/3.4.2/lib/python3.4/urllib/parse.py'>
I've imported a module, and printed one of its attributes. Everything works as expected. So far, life is good.
Now, I do the same thing from the command line:
$ python -c 'import urllib; print(urllib.parse)'
Traceback (most recent call last):
File "<string>", line 1, in <module>
AttributeError: 'module' object has no attribute 'parse'
Say what?! that's not how that's supposed to work.
Ok, maybe this is a python-wide behavior; maybe modules are not immediately imported when using the -c
flag. Let's try another module:
$ python -c 'import datetime; print(datetime.datetime)'
<class 'datetime.datetime'>
What?! How does it work for datetime
and not for urllib
? I'm using the same version of python in both places (3.4.2)
Does anyone have any thoughts on this?
EDIT:
Per one of the comments:
$ which -a ipython
/Users/ashwin/.pyenv/shims/ipython
/Library/Frameworks/Python.framework/Versions/2.7/bin/ipython
/usr/local/bin/ipython
/usr/local/bin/ipython
And
$ which -a python
/Users/ashwin/.pyenv/shims/python
/Library/Frameworks/Python.framework/Versions/2.7/bin/python
/usr/bin/python
/usr/bin/python
When you run
import urllib
, it creates the module object of theurllib
module (which is actually a package) without importing its submodules (parse, request etc.).You need the parent module object (
urllib
) to be in your namespace if you want to access its submodule using attribute access. In addition to that, that submodule must already be loaded (imported). From the documentation:There is only one instance of each module, thus any changes made to the
urllib
module object (stored insys.modules['urllib']
) get reflected everywhere.You don't import
urllib.parse
, but IPython does. To prove this I'm going to create a startup file:and launch
ipython
It is the side effect of importing
pydoc
during the startup of IPython (which ipython
is /usr/local/bin/ipython):This explains why the below code fails - you only import
urllib
and nothing seems to importurllib.parse
:On the other hand, the following command works because
datetime.datetime
is not a module. It's a class that gets imported duringimport datetime
.urllib.parse
is available from Python 3 onwards. I think you might need toimport urllib.parse
, notimport urllib
. Not sure if (when) submodule import is implicit.I would guess IPython imports
urllib.parse
on startup and that is why it is available.parse
is a module not an attribute: