dynamic class/module use? (like Java's forName)

Discussion in 'Python' started by Alex Hunsley, Jul 17, 2004.

  1. Alex Hunsley

    Alex Hunsley Guest

    Does python provide a way to dynamically use modules and/or classes?
    I'm thinking in the vein of Java's Class.forName.

    As a pseudocode example, I'm looking for the following ability:


    classIWantToInstantiate = "packagenamehere.classNameHere"

    anInstanceOfThatClass = makeNewClassFromString(classIWantToInstantiate,
    parameters[])

    # now anInstanceOfThatClass refers to an instantied
    # packagenamehere.classNameHere object!



    thanks
    alex
     
    Alex Hunsley, Jul 17, 2004
    #1
    1. Advertising

  2. Alex Hunsley

    Alex Hunsley Guest

    Alex Hunsley wrote:

    > Does python provide a way to dynamically use modules and/or classes?
    > I'm thinking in the vein of Java's Class.forName.
    >
    > As a pseudocode example, I'm looking for the following ability:
    >
    >
    > classIWantToInstantiate = "packagenamehere.classNameHere"
    >
    > anInstanceOfThatClass = makeNewClassFromString(classIWantToInstantiate,
    > parameters[])
    >
    > # now anInstanceOfThatClass refers to an instantied
    > # packagenamehere.classNameHere object!
    >
    >
    >
    > thanks
    > alex


    Oops.. I goggled but not hard enough obviously! I found my answer on
    google groups:

    http://shorterlink.com/?N2HPGU

    alex
     
    Alex Hunsley, Jul 17, 2004
    #2
    1. Advertising

  3. Alex Hunsley

    Roy Smith Guest

    In article <_OdKc.29430$>,
    Alex Hunsley <> wrote:

    > Does python provide a way to dynamically use modules and/or classes?
    > I'm thinking in the vein of Java's Class.forName.


    Just out of curiosity, why do you want to do that?

    The google link you provided talked about eval and exec. My experience
    is that when I first started using Python (about 7 years ago), I used
    eval and exec a lot. Now, I can't remember the last time I ever wanted
    to use either.

    Can you give us an example of what you're trying to do? My guess,
    having not yet seen it, is that there's probably a better way to do it
    than what you're asking.
     
    Roy Smith, Jul 17, 2004
    #3
  4. Alex Hunsley

    Guest

    Roy Smith <> writes:
    >
    > Just out of curiosity, why do you want to do that?


    in order to be more flexible,
    allowing code to be integrated that is available
    only at run time of the program

    Klaus Schilling
     
    , Jul 17, 2004
    #4
  5. On Sat, 17 Jul 2004 18:00:26 GMT, rumours say that Alex Hunsley
    <> might have written:

    >Does python provide a way to dynamically use modules and/or classes?
    >I'm thinking in the vein of Java's Class.forName.


    [snip]

    Have you already considered the 'new' module? If not, give it a try.
    --
    TZOTZIOY, I speak England very best,
    "Tssss!" --Brad Pitt as Achilles in unprecedented Ancient Greek
     
    Christos TZOTZIOY Georgiou, Jul 17, 2004
    #5
  6. Alex Hunsley

    Alex Hunsley Guest

    Roy Smith wrote:
    > In article <_OdKc.29430$>,
    > Alex Hunsley <> wrote:
    >
    >
    >>Does python provide a way to dynamically use modules and/or classes?
    >>I'm thinking in the vein of Java's Class.forName.

    >
    >
    > Just out of curiosity, why do you want to do that?
    >
    > The google link you provided talked about eval and exec. My experience
    > is that when I first started using Python (about 7 years ago), I used
    > eval and exec a lot. Now, I can't remember the last time I ever wanted
    > to use either.
    >
    > Can you give us an example of what you're trying to do? My guess,
    > having not yet seen it, is that there's probably a better way to do it
    > than what you're asking.


    Ok, the situation is that I am parsing a file that has "actions" (or
    commands) embedded in it. Different actions cause different things to
    happen to the file which is being preprocessed for something. Now, since
    I will have many actions, and want my python to be extensible so other
    users can add their own actions, rather than hard coding each action
    like so:

    if (actionString == "blah"):
    blahThang = blah(constructor stuff)
    blahThang.doSomething()
    else if (actionString == "blah2"):
    blahThang2 = blah2(constructor stuff)
    blahThang2.doSomething()
    else if (actionString == "blah3"):
    blahThang3 = blah3(constructor stuff)
    blahThang3.doSomething()
    else if (actionString == "blah2"):
    # etc etc

    .... I can have a different python class (and hence source file) for each
    action, and the code for launching an action becomes generic (i.e.
    creates instance of the class based on the command string and calls
    agreed methods on it). I prefer this to the altyernative of hardcoding
    each action with an 'if', as above, and then getting another user who
    wants to extend my project have to add yet another if clause as well as
    some code.
    Another advantage of this generic approach is that it encourages other
    users extending my code to put actions in seperate files, one per
    action, rather than adding 'magic' code into the above 'if' chaos.

    Basically, modular actions is the idea!

    I'd be keen to hear peoples thoughts on my approach.

    thanks
    alex
     
    Alex Hunsley, Jul 18, 2004
    #6
  7. Alex Hunsley

    Alex Hunsley Guest

    Roy Smith wrote:

    > In article <_OdKc.29430$>,
    > Alex Hunsley <> wrote:
    >
    >
    >>Does python provide a way to dynamically use modules and/or classes?
    >>I'm thinking in the vein of Java's Class.forName.

    >
    >
    > Just out of curiosity, why do you want to do that?
    >


    p.s. to my last response:

    I've just read Robert Brewer's reply, and to rephrase myself as I to
    him: I'm trying to do the strategy pattern in a modular fashion. (i.e.
    no big string of 'ifs' and hardcoded actions.)

    alex
     
    Alex Hunsley, Jul 18, 2004
    #7
  8. Alex Hunsley

    Terry Reedy Guest

    "Alex Hunsley" <> wrote in message
    news:8glKc.31979$...
    >
    > if (actionString == "blah"):
    > blahThang = blah(constructor stuff)
    > blahThang.doSomething()
    > else if (actionString == "blah2"):
    > blahThang2 = blah2(constructor stuff)
    > blahThang2.doSomething()
    > else if (actionString == "blah3"):
    > blahThang3 = blah3(constructor stuff)
    > blahThang3.doSomething()
    > else if (actionString == "blah2"):
    > # etc etc


    The Python idiom for something like the above is to use a dict instead of
    if/else.
    It is especially useful when you want to add alternatives at runtime.
    Something like

    actions = { 'blah':blah, 'blah2', blah2, 'blah3':blah3, ...}
    # easily extended at runtime
    ....
    actions[actionString](constructor_stuff).doSomething

    Terry J. Reedy
     
    Terry Reedy, Jul 18, 2004
    #8
  9. Alex Hunsley

    Paul McGuire Guest

    "Alex Hunsley" <> wrote in message
    news:8glKc.31979$...
    <snip>
    > Ok, the situation is that I am parsing a file that has "actions" (or
    > commands) embedded in it. Different actions cause different things to
    > happen to the file which is being preprocessed for something. Now, since
    > I will have many actions, and want my python to be extensible so other
    > users can add their own actions, rather than hard coding each action
    > like so:
    >
    > if (actionString == "blah"):
    > blahThang = blah(constructor stuff)
    > blahThang.doSomething()
    > else if (actionString == "blah2"):
    > blahThang2 = blah2(constructor stuff)
    > blahThang2.doSomething()
    > else if (actionString == "blah3"):
    > blahThang3 = blah3(constructor stuff)
    > blahThang3.doSomething()
    > else if (actionString == "blah2"):
    > # etc etc

    <snip>

    Alex,

    Have a look at how pyparsing (http://pyparsing.sourceforge.net) supports the
    attachment of actions to parse expressions within a grammar.

    -- Paul
     
    Paul McGuire, Jul 18, 2004
    #9
  10. Alex Hunsley

    Alex Hunsley Guest

    Terry Reedy wrote:
    > "Alex Hunsley" <> wrote in message
    > news:8glKc.31979$...
    >
    >> if (actionString == "blah"):
    >> blahThang = blah(constructor stuff)
    >> blahThang.doSomething()
    >> else if (actionString == "blah2"):
    >> blahThang2 = blah2(constructor stuff)
    >> blahThang2.doSomething()
    >> else if (actionString == "blah3"):
    >> blahThang3 = blah3(constructor stuff)
    >> blahThang3.doSomething()
    >> else if (actionString == "blah2"):
    >> # etc etc

    >
    >
    > The Python idiom for something like the above is to use a dict instead of
    > if/else.
    > It is especially useful when you want to add alternatives at runtime.
    > Something like
    >
    > actions = { 'blah':blah, 'blah2', blah2, 'blah3':blah3, ...}
    > # easily extended at runtime
    > ...
    > actions[actionString](constructor_stuff).doSomething
    >
    > Terry J. Reedy


    Interesting, I hadn't thought of using a dict.
    Using a dict would be better than 'if's, but would still require a
    central part of the code to know about all the actions!
    My way allows new classes to be presented and used without altering
    existing code.
    Also my method forces new actions to interface with 'central' code via
    the available official interface, rather than having new actions
    potentially put in the central code and hence have access to things
    directly (which isn't a good OO design).
     
    Alex Hunsley, Jul 18, 2004
    #10
  11. Alex Hunsley

    Alex Hunsley Guest

    Paul McGuire wrote:

    > "Alex Hunsley" <> wrote in message
    > news:8glKc.31979$...
    > <snip>
    >
    >>Ok, the situation is that I am parsing a file that has "actions" (or
    >>commands) embedded in it. Different actions cause different things to
    >>happen to the file which is being preprocessed for something. Now, since
    >>I will have many actions, and want my python to be extensible so other
    >>users can add their own actions, rather than hard coding each action
    >>like so:
    >>
    >> if (actionString == "blah"):
    >> blahThang = blah(constructor stuff)
    >> blahThang.doSomething()
    >> else if (actionString == "blah2"):
    >> blahThang2 = blah2(constructor stuff)
    >> blahThang2.doSomething()
    >> else if (actionString == "blah3"):
    >> blahThang3 = blah3(constructor stuff)
    >> blahThang3.doSomething()
    >> else if (actionString == "blah2"):
    >> # etc etc

    >
    > <snip>
    >
    > Alex,
    >
    > Have a look at how pyparsing (http://pyparsing.sourceforge.net) supports the
    > attachment of actions to parse expressions within a grammar.
    >
    > -- Paul
    >

    Interesting, Paul! thanks for link.
    lex

    >
     
    Alex Hunsley, Jul 18, 2004
    #11
  12. On Sat, 17 Jul 2004, Alex Hunsley wrote:

    > classIWantToInstantiate = "packagenamehere.classNameHere"
    >
    > anInstanceOfThatClass = makeNewClassFromString(classIWantToInstantiate,
    > parameters[])
    >
    > # now anInstanceOfThatClass refers to an instantied
    > # packagenamehere.classNameHere object!


    getattr is probably the best way to go about this:

    packagename,classname = classIWantToInstantiate.split('.')
    myclass = getattr(locals()[packagename], classname)

    Or, if you want to support nested classes:

    classnames = classIWantToInstantiate.split('.')
    myclass = locals()[classnames[0]]
    for classname in classnames[1:]:
    myclass = getattr(myclass, classname)

    Then you can just instantiate the class with myclass().

    (Question for those in the know: why isn't there a way you can reference
    the current module, i.e. so getattr(current_module,something) would be
    equivalent to locals()[something]?)
     
    Christopher T King, Jul 19, 2004
    #12
  13. Am Sonntag, 18. Juli 2004 20:52 schrieb Alex Hunsley:
    > Interesting, I hadn't thought of using a dict.
    > Using a dict would be better than 'if's, but would still require a
    > central part of the code to know about all the actions!
    > My way allows new classes to be presented and used without altering
    > existing code.
    > Also my method forces new actions to interface with 'central' code via
    > the available official interface, rather than having new actions
    > potentially put in the central code and hence have access to things
    > directly (which isn't a good OO design).


    What I always do when I'm in your position to have an extendable API is to
    create a Registry with which the possible actions can register, a general
    parsing engine, which just does a dictionary lookup on some word (the
    dictionary being maintained by the module which contains the Registry), and
    then calls of into the appropriate code. All other modules can also use the
    Registry.

    Something like this:

    ====
    Registry.py

    pluginDict = {}

    def registerPlugin(name,plugincallable):
    pluginDict[name] = plugincallable

    def queryPlugin(name):
    return pluginDict[name]()

    ====
    Plugins/__init__.py

    pass

    ====
    Plugins/Module1.py

    import Registry

    class Callable1(object):
    def __init__(self):
    print "Instantiating Callable1."

    def test_method(self,*args,**kwargs):
    print "In test_method."
    print args, kwargs

    Registry.register("callable1",Callable1)

    ====
    Plugins/Module2.py

    import Registry

    class Callable2(object):
    def __init__(self):
    print "Instantiating Callable2."

    Registry.register("callable2",Callable2)

    ====
    Plugins.py

    import os

    for fname in os.listdir("Plugins"):
    try:
    __import__("Plugins.%s" % fname[-3],globals(),locals(),[])
    except:
    print "Warning: Couldn't import plugin:", fname

    ====
    Main.py

    import Registry
    import Plugins

    mod1 = Registry.queryPlugin("callable1")
    print mod1
    mod2 = Registry.queryPlugin("callable2")
    print mod2

    ====
    ParseCommand.py

    import Registry

    command = "callable1.test_method test 123 how are you?"
    cmd = command.split(" ")
    mod, attr = cmd[0].split(".",1)
    mod = Registry.queryPlugin(mod)
    getattr(mod,attr)(*cmd[1:])


    This code only requires you to put all plugin modules into the subdirectory
    Plugins of the main program directory, and could easily be extended by
    rewriting Plugins.py to accomodate on demand loading/reloading of plugins,
    etc. ParseCommand.py can also easily be made more "intelligent" concerning
    the parsing of the actual command-line.

    Is this extensible enough? ;)

    HTH!

    Heiko.
     
    Heiko Wundram, Jul 19, 2004
    #13
  14. Am Montag, 19. Juli 2004 19:54 schrieb Heiko Wundram:
    > ...
    > Something like this:


    Err, that code was untested, please substitute:

    > ====
    > Plugins/Module1.py
    >
    > import Registry
    >
    > class Callable1(object):
    > def __init__(self):
    > print "Instantiating Callable1."
    >
    > def test_method(self,*args,**kwargs):
    > print "In test_method."
    > print args, kwargs
    >

    - Registry.register("callable1",Callable1)
    + Registry.registerPlugin("callable1",Callable1)

    > ====
    > Plugins/Module2.py
    >
    > import Registry
    >
    > class Callable2(object):
    > def __init__(self):
    > print "Instantiating Callable2."
    >

    - Registry.register("callable2",Callable2)
    + Registry.registerPlugin("callable2",Callable2)

    ....

    HTH!

    Heiko.
     
    Heiko Wundram, Jul 19, 2004
    #14
  15. Am Montag, 19. Juli 2004 19:54 schrieb Heiko Wundram:
    > Something like this:


    And another bug... Hmmm... I should never post code which I don't intend to
    test in the interpreter...

    > ====
    > ParseCommand.py
    >
    > import Registry

    + import Plugins

    ....

    Heiko.
     
    Heiko Wundram, Jul 19, 2004
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. H.MuthuKumaraRajan

    .class and Class.forName

    H.MuthuKumaraRajan, Nov 6, 2003, in forum: Java
    Replies:
    11
    Views:
    1,786
    H.MuthuKumaraRajan
    Nov 7, 2003
  2. cyril
    Replies:
    2
    Views:
    3,951
    cyril
    Aug 25, 2004
  3. Madni
    Replies:
    1
    Views:
    5,936
  4. jean-francois
    Replies:
    2
    Views:
    625
  5. femto femto
    Replies:
    3
    Views:
    191
    Trans
    Aug 17, 2006
Loading...

Share This Page