Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python calling classes dynamically

I want to call python classes dynamically,

These are the classes that I want to call

class AutosoukModelMakeFuzzyComparisonModule:
    def __init__(self,configurationLoader=None, moduleConfigurationFile=None, settings=None):
        pass

and

class DefaultFuzzyComparisonModule:
    def __init__(self,configurationLoader, moduleConfigurationFile, settings = None):
        pass

and these too classes located in fuzzymodules folder

and I call them from ** FuzzyComparisonPipeline.py** which is in the same directory as fuzzymodules like this:

for module in FuzzyComparisonPipeline.fuzzyModules:
        name = module['name']
        configurationLoader = module['configurationLoader']
        moduleConfigurationFile = module['moduleConfigurationFile']
        settings = module['settings']
        module_to_import = __import__('fuzzymodules.'+name)
        instanceOfModule = getattr(module_to_import, name).__init__(configurationLoader, moduleConfigurationFile, settings)
        #instanceOfModule(configurationLoader, moduleConfigurationFile, settings)
    return item

I got this error:

   Traceback (most recent call last):
  File "path to my FuzzyComparisonPipeline.py", line 9, in process_item
    instanceOfModule = getattr(module_to_import, name).__init__(configurationLoader, moduleConfigurationFile, settings)
TypeError: module.__init__() takes at most 2 arguments (3 given)

and my question is how the init() takes 2 arguments, as you see, in both classes the init takes three arguments

Could you help please

i can't give you the whole code, because it is so complicated, everything else is working fine, i am sure of that, my problem is in calling that function.

the values of the for loop coming from this xml

<FuzzyComparison>
    <Modules>
        <Module>
            <name>AutosoukModelMakeFuzzyComparisonModule</name>
            <configurationLoader>DefaultLoader</configurationLoader>
            <configurationFile>MakesModels.conf</configurationFile>
            <settings></settings>
        </Module>
        <Module>
            <name>DefaultFuzzyComparisonModule</name>
            <configurationLoader>DefaultLoader</configurationLoader>
            <configurationFile>Buildings.conf</configurationFile>
            <settings>
                <attribute>building</attribute>
                <second>2222duxk fuck fuck</second>
            </settings>
        </Module>
    </Modules>
    </FuzzyComparison>
like image 577
Marco Dinatsoli Avatar asked Dec 02 '25 00:12

Marco Dinatsoli


2 Answers

You are retrieving a module, not the class in the module; the __import__() function returns the top-level package, not the nested module itself.

You really want to use importlib.import_module() instead here, it behaves as you expect.

Next, you want to call the class object thus retrieved, not the __init__ method directly. Let Python call that for you, it'll do so to initialise the instance you create by calling the class:

from importlib import import_module

for module in FuzzyComparisonPipeline.fuzzyModules:
    name = module['name']
    configurationLoader = module['configurationLoader']
    moduleConfigurationFile = module['moduleConfigurationFile']
    settings = module['settings']
    module_to_import = import_module('fuzzymodules.' + name)
    instance = getattr(module_to_import, name)(configurationLoader, moduleConfigurationFile, settings)
like image 158
Martijn Pieters Avatar answered Dec 03 '25 13:12

Martijn Pieters


From the documentation of __import__() -

__import__(name[, globals[, locals[, fromlist[, level]]]])

When the name variable is of the form package.module, normally, the top-level package (the name up till the first dot) is returned, not the module named by name. However, when a non-empty fromlist argument is given, the module named by name is returned.

(Emphasis mine)

So in your case, the module - fuzzymodules is being returned - not the module containing your class.

You should specify the fromlist argument as name . Example -

module_to_import = __import__('fuzzymodules.'+name, fromlist=name)

Also , another issue is that you should not directly call the __init__() function of the class to create an object for it, instead call it directly, Example -

instanceOfModule = getattr(module_to_import, name)(configurationLoader, moduleConfigurationFile, settings)

__init__() function is called for initialization after the object has been created.

like image 39
Anand S Kumar Avatar answered Dec 03 '25 13:12

Anand S Kumar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!