I need some clarification on how module and class level imports are handled when coexisting in the same namespace. See the following examples:
Works:
import datetime
print datetime.datetime.utcnow()
Fails:
from datetime import datetime
print datetime.datetime.utcnow()
Error: AttributeError: type object 'datetime.datetime' has no attribute 'datetime'
Works:
from datetime import datetime # Is this ignored?
import datetime
print datetime.datetime.utcnow()
What exactly is happening in the 3rd example? Is the second module import replacing the class-specific first import? Does this mean that module and class level imports shouldn't be mixed in the same namespace?
5 Answers 5
There is no priority is such. The outcome is determined by the order in which import statements are executed, as follows.
If you try to import several things called X into your namespace, each import would rebind X to whatever it's importing.
Therefore at the end it will be last import that'll be in effect as far as the name X in concerned.
This is precisely what happens in your third example:
from datetime import datetime # This isn't ignored, but the name is immediately rebound
# by the next line
import datetime # Rebinds the name
Comments
Some of the IDE's that support python would give you the explanation, but yes, you're redefining (overwriting, replacing) the import in the 3rd example. Each name within a file is distinct. If you need access to a module and a class that share a name you need to use something like from datetime import datetime as dt.
Comments
An import is really just an assignment: it sets a name in your current namespace. So, in the third case, you set the name datetime as equal to the datetime class, then immediately reassign it to the datetime module.
Comments
There is no reason to do it like this:
from datetime import datetime
print datetime.datetime.utcnow()
this code, on the other hand, would do exactly what you want it to:
from datetime import datetime
print datetime.utcnow()
Comments
Your first example imports the datetime module and provides a datetime label in the local namespace representing it, then calls the utcnow() method of the datetime object belonging to the datetime module. The second adds the datetime.datetime object (not the module) to the local namespace with the label datetime, but the datetime object has no attribute datetime, so you get the exception. The third example assigns the datetime.datetime object to the label of that name in the namespace, then reassigns the label to the datetime module. So ignoring the mechanics of import that are irrelevant to this question (basically, adding modules to sys.modules if they are not there yet), what you have is equivalent to:
datetime = sys.modules['datetime']
datetime.datetime.utcnow()
then
datetime = sys.modules['datetime'].datetime
datetime.datetime.utcnow()
then
datetime = sys.modules['datetime'].datetime
datetime = sys.modules['datetime']
datetime.datetime.utcnow()