getattr from local scope

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • rob.haswell@gmail.com

    #1

    getattr from local scope

    Hey there

    My question is pretty simple - I want to use something like getattr to
    grab a symbol from the local scope from a string.

    Basically my application has a scheduler which stores names of
    functions
    defined in the "schedule" module in a database, to be run on certain
    days.
    Every night I call schedule.RunSch edule, which grabs all the rows on
    the
    database that have to be run now, and I want to call the function
    defined
    the same module according to that string.

    I know I can use eval, but I've always been told that if you're using
    eval, you're doing it wrong. Also not using eval limits the scope
    damage
    that can be caused by any errors in my application which could cause
    the
    database to be poisoned.

    Cheers for any help :-)

    -Rob

  • Edward Elliott

    #2
    Re: getattr from local scope

    rob.haswell@gma il.com wrote:[color=blue]
    > Basically my application has a scheduler which stores names of functions
    > defined in the "schedule" module in a database, to be run on certain
    > days. Every night I call schedule.RunSch edule, which grabs all the rows on
    > the database that have to be run now, and I want to call the function
    > defined the same module according to that string.[/color]

    I know that sys.modules[__name__] gives the module object for the current
    module. You could do:

    m = sys.modules[__name__] # M now current module object
    func = m.__dict__ [fs] # func has function named by string fs
    func()

    If func isn't in the current module, replace __name__ with 'Foo'. Add
    try/catch as appropriate in case fs doesn't exist in module M.

    If your database stores the function arguments in the same string as the
    function name, you'll have to parse them out separately.

    I make no claims to this solution being optimal, as it pretty much
    stretches my knowledge of Python modules and reflection.

    Comment

    • Alex Martelli

      #3
      Re: getattr from local scope

      Edward Elliott <nobody@127.0.0 .1> wrote:
      [color=blue]
      > rob.haswell@gma il.com wrote:[color=green]
      > > Basically my application has a scheduler which stores names of functions
      > > defined in the "schedule" module in a database, to be run on certain
      > > days. Every night I call schedule.RunSch edule, which grabs all the rows on
      > > the database that have to be run now, and I want to call the function
      > > defined the same module according to that string.[/color]
      >
      > I know that sys.modules[__name__] gives the module object for the current
      > module. You could do:
      >
      > m = sys.modules[__name__] # M now current module object
      > func = m.__dict__ [fs] # func has function named by string fs
      > func()[/color]

      sys.modules[__name__].__dict__ may be more handily accessed by the
      built-in function globals().


      Alex

      Comment

      • Edward Elliott

        #4
        Re: getattr from local scope

        Alex Martelli wrote:[color=blue]
        > sys.modules[__name__].__dict__ may be more handily accessed by the
        > built-in function globals().[/color]

        Well there you go. Glad it's not that awkward.

        Comment

        • Fredrik Lundh

          #5
          Re: getattr from local scope

          rob.haswell@gma il.com wrote:
          [color=blue]
          > I know I can use eval, but I've always been told that if you're using
          > eval, you're doing it wrong. Also not using eval limits the scope damage
          > that can be caused by any errors in my application which could cause
          > the database to be poisoned.[/color]

          a more robust approach is to explicitly add public entry points to a
          dictionary, and dispatch via that dictionary:

          a simple decorator can be handy for this purpose:

          registry = {}

          def public(func):
          registry[func.__name__] = func

          @public
          def func1():
          print "func1"

          @public
          def func2():
          print "func2"

          def func3():
          print "internal func3"

          registry["func1"]()
          registry["func3"]() # this will fail

          in pre-decorator versions of python, this can be implemented either
          by explicitly registering the entry points:

          def func2():
          print "func2"
          public(func2)

          or

          def func2():
          print "func2"
          registry["func2"] = func2

          or by using a prefix to make accidental publishing less likely:

          def public_func2():
          print "func2"

          globals()["public_" + funcname]()

          and/or by making all the callbacks methods of a class, and use getattr
          on an instance of that class.

          </F>



          Comment

          Working...