1

I have scenario where I am passing a file name and checking if it has argument start as constructor if it has then I have to create instance of that class.

Consider the example where I have a file named test.py which have three class namely A,B,C now only class A has start parameter others have other different parameter or extra parameter.

#test.py
class A:
    def __init__(self, start=""):
        pass

class B:
    def __init__(self, randomKeyword, start=""):
        pass

class C:
    def __init__(self):
        pass

Now I want to write a script which takes test.py as an argument and create instance of A. Till now my progress is

detail = importlib.util.spec_from_file_location('test.py', '/path/to/test.py')
module = importlib.util.module_from_spec(detail)
spec.loader.exec_module(mod)

Bacially I need to write a program which finds init argument of all class in file and create an instance of file with start as init argument.

10
  • 2
    That doesn't sound like a sensible approach to anything, really…?! You don't know what the file contains really, and you don't really know what you're instantiating, you're just instantiating it because it happens to have a parameter with a certain name…?! Commented Feb 24, 2021 at 10:23
  • @deceze It's a sensible approach to do a Python exercise :) Commented Feb 24, 2021 at 10:33
  • 1
    @user2357112supportsMonica Yes. Yes it is. Commented Feb 24, 2021 at 10:43
  • 1
    That's kinda what I'm saying. You're executing some unknown user code merely on the basis of it having a parameter named "start". What if it has many different classes in that file that all happen to accept "start", but you're not supposed to use them? You're basically defining an "interface" there, saying "name the parameter of a class I'm supposed to run 'start'". In return that means that name can't be used for anything else inside that file, which is a weird restriction. Commented Feb 24, 2021 at 11:50
  • 1
    You'd usually have a method/function/class of a specific name like main and/or the user passes that name to your program. E.g. in the notation /path/to/test.py:MyClass.start or something like that. Commented Feb 24, 2021 at 12:31

1 Answer 1

2

As mentioned by @deceze it's not a good idea to instantiate a class on the basis of it's init parameter as we're not sure what is there. But it's possible to do it. So I am posting this answer just so that you know how it can be done.

#test.py
class A:
    def __init__(self, start=""):
        pass

class B:
    def __init__(self, randomKeyword, start=""):
        pass

class C:
    def __init__(self):
        pass

One of the possibility is

#init.py
import importlib.util
from inspect import getmembers, isclass, signature

detail = importlib.util.spec_from_file_location('test.py', '/path/to/test.py')
module = importlib.util.module_from_spec(detail)
spec.loader.exec_module(module)

for name, data in getmembers(mod, isclass):
    cls = getattr(mod, name)
    parameter = signature(cls.__init__).parameters.keys()
    # parameter start
    if len(parameter) == 2 and 'start' in parameter:
        object = cls(start="Whatever you want")

Ofcourse it's not the best approach so more answer are welcome and if you are in this scenario consider @deceze comment and define a builder.

Sign up to request clarification or add additional context in comments.

Comments

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.