Why can't I import from a module alias?
In short:
You can think of the loading process in that way:
You can load a module into your program, in the form of a variable. You can name the variable for using the module whatever you want. But, the loading process, is based on the name of the module's file, not "module variables".
Long version:
import re
creates a global variable named re
that serves as the "module portal", in the way it provides the ability to use the module operations.
Most alike, import re as regex
creates such a "portal" under the variable named regex
.
But, when looking to create such portal and load the module functionality into it, the importer does not use such references. Instead, it looks for the module in your python \Lib
directory, or your current working directory, as a file named re.py
(or whatever is the name of the module you import).
The import
instructions does not address variables, but files, like #include<stdio.h>
in C. They have their "own syntax", and set of instructions, as ruled by the interpreter structure, which is, to that case, the interpretation of re
as a file name rather than a variable and as
for ruling the name of the module "portal".
That is why regex
is an operation alias for the portal for re
, but not an importation alias for the module (for that purpose you'll have to use the name of the file).
I have used terms like "module portal" and "operation alias" since I have not found any standard terms for these. Most of the modules and importer mechanics is related to the interpreter implementation. In CPython (where the usage of the C API is common among developers), for example,
create_module
creates modules for the importer (in the form ofPyObject
s) using the provided specifications for the module, and thePyModule_NewObject
andPyModule_New
functions for the module instance creation that bears the module attributes. These can be viewed in the C API modules decumentation.When I mentioned the term "portal" as a way to reference the variable created by the
import
statement, I meant to refer to it as a static portal, not a dynamic one. A change in the module file will not reflect in a running program that already imported it (as long as it didn't reload it), as it will load a copy of the module and use it, rather than asking the module file for the operations when encountering need.
Here is pretty much how the variable loading goes realtime:
>>> import re
>>> re
<module 're' from 'C:\\Programs\\Python35\\lib\\re.py'>
>>> import re as regex
>>> regex
<module 're' from 'C:\\Programs\\Python35\\lib\\re.py'>
You can see that re
is the module referenced, and it was loaded from the file C:\Programs\Python35\lib\re.py
(may change depending on where your python is installed).
You cannot treat the module name in import statements as variables. If that was the case, surely your initial import would fail because re
is not yet a declared variable. Basically the import statement is semantic sugar; it is a statement of its own with its own rules.
One such rule is this: The written module name is understood as if it was a string. That is, it does not lookup a variable with the name re
, instead it uses the string value 're'
directly as the sought after module name. It then searches for a module/package (file) with this name and does the import.
This is the only situation (Edit: Well, see the discussion in the comments...) in the language where this behavior is seen, which is the cause of the confusion. Consider this alternative syntax, which is much more in line with the rest of the Python language:
import 're'
# Or alternatively
module_name = 're'
import module_name
Here, variable expansion is assumed in the import statement. As we know this is not the syntax which was actually chosen for the import statement. One can discuss which syntax is the better one, but the above is definitely more harmonious with the rest of the language syntax.
To get a definite answer on this you'll have to ask the designers themselves but, I think you're asking the wrong question.
The question shouldn't be: Why is it done this way?" but, it should be, what would be the benefit of doing it the way you're asking? Surely it can be done but why should it?
As is the import
statement is dead simple and very intuitive, you give it a file name, it tries to finds load it up. You even get fancy as
and from
but, the concept is simply, you write filenames and you let it be.
What would obfuscating it and making it harder understand achieve, the only achievement is making things arguably more complex.
Python has a history of looking for the rationale behind changes to its design, people asking why aren't function
objects subclassable will get a "Why should they?" reply; this behavior doesn't really have a use-case. As is, the import
is simple, intuitive and reminiscent of including/using files in other languages.