3

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>
11
  • 1
    You'd not call __init__ directly, you'd call the object itself (just remove the .__init__ part). But clearly you are not getting the right code here as you are trying to instantiate that doesn't take 3 arguments. If you gave us an actual traceback we might be able to be of more help. Commented Jul 25, 2015 at 14:47
  • what is name in your example? Which .py file does it lie in, what is the directory structure for that .py file? Also, 1. __init__() in your examples take 4 arguments (the first being the object itself) . 2. __init__() is not used for object creation, its used for object initialization , but seems like you want to use it for object creation (but it should not be used like that) . Commented Jul 25, 2015 at 14:50
  • @MartijnPieters I will update the question Commented Jul 25, 2015 at 14:51
  • @AnandSKumar I will update the question and add more context Commented Jul 25, 2015 at 14:51
  • @MartijnPieters i tried my best to give you the whole picture Commented Jul 25, 2015 at 14:57

2 Answers 2

3

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)
Sign up to request clarification or add additional context in comments.

2 Comments

and pleas last question, now i have an instance of the class, right? so lets say that i can do something like : instance.myFunction() ?
@MarcoDinatsoli: yes, you have an instance of the class, so you can call methods on it.
2

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.

1 Comment

I really appreciate the efforts, but Martijn Pieters has been helping me from the beginning, i must accept his answer (if he writes one), plus one for your efforts, I wish i could accept both of your answers

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.