How do the following two statements differ and what are the consequences of each?
Import as:
from module.submodule import someclass as myclass
Assign to a variable:
from module.submodule import someclass
myclass = someclass
Importing refers to allowing a Python file or a Python module to access the script from another Python file or module. You can only use functions and properties your program can access. For instance, if you want to use mathematical functionalities, you must import the math package first.
The difference between import and from import in Python is: import imports the whole library. from import imports a specific member or members of the library.
So there's four different ways to import: Import the whole module using its original name: pycon import random. Import specific things from the module: pycon from random import choice, randint. Import the whole module and rename it, usually using a shorter variable name: pycon import pandas as pd.
User variables are specific to the SEER*Stat database for which they were created, but their definitions can be imported into other databases. Your process for doing so may differ depending on whether you have access to the original database.
The bytecode output given here is for Python 3.4, but the code to produce the bytecode should work on any version and the same general principles apply.
Harness:
from dis import dis
def compile_and_dis(src):
dis(compile(src, '<string>', 'exec'))
Case 1:
>>> compile_and_dis('from module.submodule import someclass as myclass')
1 0 LOAD_CONST 0 (0)
3 LOAD_CONST 1 (('someclass',))
6 IMPORT_NAME 0 (module.submodule)
9 IMPORT_FROM 1 (someclass)
12 STORE_NAME 2 (myclass)
15 POP_TOP
16 LOAD_CONST 2 (None)
19 RETURN_VALUE
This is the only approach that only adds one name (myclass
) into the current locals()
(i.e. __dict__
, which will become globals()
for everything defined in the module). It is also the shortest bytecode.
This method will raise ImportError
if someclass
is not found in module.submodule
. It will, however, attempt to load module.submodule.someclass
as a module.
Case 2:
>>> compile_and_dis('from module.submodule import someclass; myclass = someclass')
1 0 LOAD_CONST 0 (0)
3 LOAD_CONST 1 (('someclass',))
6 IMPORT_NAME 0 (module.submodule)
9 IMPORT_FROM 1 (someclass)
12 STORE_NAME 1 (someclass)
15 POP_TOP
16 LOAD_NAME 1 (someclass)
19 STORE_NAME 2 (myclass)
22 LOAD_CONST 2 (None)
25 RETURN_VALUE
This is nearly identical to case 1, except that it leaks a second name (someclass
) into the local namespace. If the import and assignment are not contiguous, you do run the theoretical risk of reusing the name for something else, but if you're shadowing names you have horrible design anyway.
Note the useless STORE_NAME
/LOAD_NAME
cycle in the bytecode (around an unrelated POP_TOP
).
Case 3:
>>> compile_and_dis('from module import submodule; myclass = submodule.someclass')
1 0 LOAD_CONST 0 (0)
3 LOAD_CONST 1 (('submodule',))
6 IMPORT_NAME 0 (module)
9 IMPORT_FROM 1 (submodule)
12 STORE_NAME 1 (submodule)
15 POP_TOP
16 LOAD_NAME 1 (submodule)
19 LOAD_ATTR 2 (someclass)
22 STORE_NAME 3 (myclass)
25 LOAD_CONST 2 (None)
28 RETURN_VALUE
This approach leaks submodule
into the local namespace. It does not raise ImportError
if the class is not found, rather it raises AttributeError
during the assignment. It does not attempt to load module.submodule.someclass
as a module (and in fact doesn't even care whether or not module.submodule
is a module).
Case 4:
>>> compile_and_dis('import module.submodule as submodule; myclass = submodule.someclass')
1 0 LOAD_CONST 0 (0)
3 LOAD_CONST 1 (None)
6 IMPORT_NAME 0 (module.submodule)
9 LOAD_ATTR 1 (submodule)
12 STORE_NAME 1 (submodule)
15 LOAD_NAME 1 (submodule)
18 LOAD_ATTR 2 (someclass)
21 STORE_NAME 3 (myclass)
24 LOAD_CONST 1 (None)
27 RETURN_VALUE
This is similar to case 3 but requires that module.submodule
be a module.
Case 5:
>>> compile_and_dis('import module.submodule; myclass = module.submodule.someclass')
1 0 LOAD_CONST 0 (0)
3 LOAD_CONST 1 (None)
6 IMPORT_NAME 0 (module.submodule)
9 STORE_NAME 1 (module)
12 LOAD_NAME 1 (module)
15 LOAD_ATTR 2 (submodule)
18 LOAD_ATTR 3 (someclass)
21 STORE_NAME 4 (myclass)
24 LOAD_CONST 1 (None)
27 RETURN_VALUE
This approach is similar to case 4, although the 2 attribute loads are at different places so a different variable leaks into the local namespace.
The main difference is that in your variable assignment example, someclass
is still available as a name. That'll lead to issues when importing types with the same name.
from datetime import datetime
from arrow import datetime # problem!
To fix this:
from datetime import datetime
from arrow import datetime as arrow_datetime
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With