Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using modules imported from another import

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?

like image 871
datta Avatar asked Oct 25 '17 12:10

datta


2 Answers

They are available in the following namespace:

import alt
print (alt.os.getcwd())
like image 107
bluszcz Avatar answered Nov 15 '22 18:11

bluszcz


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:

  1. Direct import (recommended):

    import alt
    import os
    print(os.getcwd())
    
  2. Use the reference in alt (harder to read/trace):

    import alt
    print(alt.os.getcwd())
    
  3. 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:

  1. Unchanged.
  2. print(alt.getcwd()) since alt.os no longer exists.
  3. Unchanged.
like image 21
Mad Physicist Avatar answered Nov 15 '22 16:11

Mad Physicist