0

I'm trying to import different modules in a class:

class TCON_COMMS(object):
    TCON_COMMS_AARDVARK = 0
    TCON_COMMS_GPU = 1
    TCON_COMMS_SMC_I2C = 2
    def __init__(self, TCON_COMMS_METHOD=0):
        self.TCON_COMMS_METHOD = TCON_COMMS_METHOD
        if self.TCON_COMMS_METHOD == self.TCON_COMMS_AARDVARK:
            print("Using Aardvark for TCON communication.")
            from i2c_helper_aardvark import *
        elif self.TCON_COMMS_METHOD == self.TCON_COMMS_GPU:
            print("Using AUX for TCON communication.")
            from i2c_helper_aux import *
        else:
            print("Using SMC for TCON communication.")
            from i2c_helper_smc import *

When I write this, I get:

SyntaxWarning: `import *` only allowed at module level.

What does it mean?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Hiep Pham
  • 11
  • 1
  • 1

2 Answers2

3

Inside a function, local variables are stored in numbered slots, rather than in a dictionary the way global variables are stored. This means the Python compiler needs to know all the names of the function's local variables before it creates the function's code object, so it can translate each local variable access to an appropriate bytecode to read or write from the slot.

When you do from some_module import *, the exact names that get imported can't be known ahead of time. It's up to some_module what names it defines (or puts in __all__, if it has one). This means the compiler can't see the names ahead of time and assign each name to a slot. Not knowing the names up front is not an issue when importing at the top level, as each name/object pair will just be added to the module's globals dictionary.

To make your code work, you either need to import just the module (and access the module's contents as attributes) or you can explicitly name the items you want to import from it. Which is best depends on your taste (and perhaps how many different names you need from the modules).

I don't know what exactly you need from your i2c_helper_whatever modules, so I can't give an example of explicitly listed names, but here's an example that uses an as clause on a regular import to give the same name (in the local namespace) to whatever module is selected (I don't know if the name I picked is a good one, use your own judgement):

def __init__(self, TCON_COMMS_METHOD=0):
    self.TCON_COMMS_METHOD = TCON_COMMS_METHOD
    if self.TCON_COMMS_METHOD == self.TCON_COMMS_AARDVARK:
        print("Using Aardvark for TCON communication.")
        import i2c_helper_aardvark as i2c_helper
    elif self.TCON_COMMS_METHOD == self.TCON_COMMS_GPU:
        print("Using AUX for TCON communication.")
        import i2c_helper_aux as i2c_helper
    else:
        print("Using SMC for TCON communication.")
        import i2c_helper_smc as i2c_helper

    i2c_helper.something() # this will call a function from whichever module was imported
Blckknght
  • 100,903
  • 11
  • 120
  • 169
-1

It means that you can't use from module import * inside a class, function, or otherwise. Move them to the top of the file.

Harvey
  • 5,703
  • 1
  • 32
  • 41