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>
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)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With