acdr
acdr

Reputation: 4716

Why can I not import from a module in memory

I can do import module as md

I can do import module.submodule as smd

So why can't I do either of the following?

import module as md
import md.submodule as smd

or

import module as md
from md import submodule as smd

Asked differently: why do I have to use the long name, rather than the name I gave it?

After the first line, md should just be a first-class object in memory. Why was the decision made not to let me import from this object? (Especially considering the code "reads" as if module is already available in memory at the start - the Python guys explicitly chose for this syntax as opposed to something like md = import("module"))

Upvotes: 2

Views: 84

Answers (2)

Markon
Markon

Reputation: 4600

Just by having a look at what the module dis and its documentation say might clarify what happens in background.

>>> def g():
...   import numpy as np
... 
>>> def h():
...   import np.ma as ma # note: np is not defined!
... 
>>> dis.dis(g)
  2       0 LOAD_CONST               1 (-1)
          3 LOAD_CONST               0 (None)
          6 IMPORT_NAME              0 (numpy)
          9 STORE_FAST               0 (np)
         12 LOAD_CONST               0 (None)
         15 RETURN_VALUE        
>>> dis.dis(h)
  2       0 LOAD_CONST               1 (-1)
          3 LOAD_CONST               0 (None)
          6 IMPORT_NAME              0 (np.ma)
          9 STORE_FAST               0 (np)
         12 LOAD_CONST               0 (None)
         15 RETURN_VALUE        

To quote the docs, IMPORT_NAME means:

Imports the module co_names[namei]. TOS and TOS1 are popped and provide the fromlist and level arguments of __import__(). The module object is pushed onto the stack. The current namespace is not affected: for a proper import statement, a subsequent STORE_FAST instruction modifies the namespace.

(TOS and TOS1 are the top-of-Stack and the the second top-most stack item.)

Therefore, I would say that the reason it doesn't work is that the import statement works if and only if the token you pass is really a module name (not an object), as this will be passed to the __import__ function, which requires a module name, not a reference/variable/whatever.

More information about how this works can be found on the __import__ documentation page.

Upvotes: 1

YOBA
YOBA

Reputation: 2807

Because md may be an existing module, and since python is permissive, it will let you replace its name but you can still import it whenever you want, example:

>> import urllib2 as json

This will work, even though json is a real module and could be imported, what if you wanted to import it afterwards ?

so when you will check json in this case

>> json
>> <module 'urllib2' from '/usr/lib/python2.7/urllib2.pyc'>

it is pointed to urllib2 but you can still import submodules of real json:

>> from json import tool as tl

json will remain the same as before, which is urllib2. but you can get it back

>> import json
>> <module 'json' from '/usr/lib/python2.7/json/__init__.pyc'>

So to answer your question, it is probably a way to make it still accessible to get modules from your supposed alias ( if it is a name of a real module ).

Upvotes: 3

Related Questions