Yarin
Yarin

Reputation: 183519

Understanding Python import priority

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?

Upvotes: 2

Views: 790

Answers (5)

NPE
NPE

Reputation: 500327

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

Upvotes: 6

Silas Ray
Silas Ray

Reputation: 26150

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

Upvotes: 0

Daniel Roseman
Daniel Roseman

Reputation: 599580

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.

Upvotes: 2

graywolf
graywolf

Reputation: 7490

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

Upvotes: 0

g.d.d.c
g.d.d.c

Reputation: 47988

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.

Upvotes: 2

Related Questions