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