I'm cleaning up a project that was refactored into smaller .py files. I noticed that a lot of modules are being imported again and again in various files. Some statements are in files that import another which has the same import statement used by the importing file. For example:
main.py
import alt
print (os.getcwd())
alt.py
import os
The print(os.getcwd())
throws a NameError: name 'os' is not defined
. Shouldn't os
be part of sys.modules
when the import statement is executed in alt.py?
Is it possible to use a module imported by another module that was imported first?
They are available in the following namespace:
import alt
print (alt.os.getcwd())
To answer your immediate question, it is possible but not recommended.
Imports adjust the namespace in which they are made. This means that alt
has an attribute os
that can be accessed in main
as
print(alt.os.getcwd())
This is not the recommended way, however, since it makes it less clear which actual os
module you are using. You should do import os
directly in main
. This will not create a separate module object, so do not worry about cluttering your memory with duplicate modules.
The first time an import is encountered during runtime, it is added to the dictionary sys.modules
, keyed by the fully qualified name of the module. Future import statements will look in sys.modules
for an existing reference before doing any actual work.
In your case, import alt
will create a module referenced by sys.modules['alt']
as well as by the name alt
in main
. The statement import os
in alt
will be run next. It will create a module referenced by sys.modules['os']
and alt.os
. If you were to add a line import os
in main
after import alt
, it will not create and load another module object. Instead, the name os
will be bound to the same object pointed to by sys.modules['os']
.
The following three versions of main
will all call the same getcwd
function:
Direct import (recommended):
import alt
import os
print(os.getcwd())
Use the reference in alt
(harder to read/trace):
import alt
print(alt.os.getcwd())
Using sys.modules
(really not recommended for production unless you know what you are doing):
import alt # necessary to trigger the actual import
import sys
print(sys.modules['os'].getcwd())
All imports load a full module. This even applies to imports of the form from os import getcwd
. The module sys.modules['os']
is still created. The only difference is that the importing namespace will only have access to the name getcwd
, not os
. In your case, if alt
contained from os import getcwd
instead of import os
, the three access methods would change as follows:
print(alt.getcwd())
since alt.os
no longer exists.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