Seite 1 von 1

Wie getattr() auf selbem Modul aufrufen als Dispatcher?

Verfasst: Donnerstag 24. Februar 2011, 20:11
von Hyperion
Hallo zusammen,

ich habe grad mal überlegt, dass bei vielen kleineren Scripten ein harmloser Dispatcher ja nicht immer über ein Dict aufgebaut werden müßte, so wie hier:

Code: Alles auswählen

def foo(): pass
def bar(): pass

dispatch = {"foo": foo, "bar": bar}
dispatch[sys.argv[1]]()
Sofern man die Namen als String 1:1 auf die Namen im Modul mappt, könnte man sich das Dict ja auch sparen. Mir fiel da spontan getattr() ein, allerdings benötigt das ja als ersten Parameter ein Objekt. Meine Frage ist also, ob / wie man an das Objekt des Moduls zugreifen kann?

Code: Alles auswählen

def foo(): pass
def bar(): pass

getattr(???, sys.argv[1])()
Oder kann man darauf gar nicht zugreifen? Gibt es dann ggf. eine Alternative, um von einem String auf ein Funktionsobjekt zu schließen?

Re: Wie getattr() auf selbem Modul aufrufen als Dispatcher?

Verfasst: Donnerstag 24. Februar 2011, 20:34
von derdon
Du kannst __main__ explizit importieren und dann auf dessen Attribute zugreifen. Ich weiß aber nicht, ob es das ist, was du vorhast. Habe deinen Plan ehrlich gesagt nicht wirklich verstanden.

Re: Wie getattr() auf selbem Modul aufrufen als Dispatcher?

Verfasst: Donnerstag 24. Februar 2011, 20:44
von derdon
Ah, jetzt verstehe ich! Also ich würde wie gesagte __main__ importieren und das inspect-Modul nutzen, um Funktionen herauszufiltern.

Code: Alles auswählen

>>> import __main__                                                                               
>>> import inspect                                                                                
>>> inspect.getmembers(__main__, inspect.isfunction)                                              
[]                                                                                                
>>> def foo(a=42): pass                                                                           
...                                                                                               
>>> def bar():                                                                                    
...     print 23                                                                                  
...                                                                                               
>>> inspect.getmembers(__main__, inspect.isfunction)                                              
[('bar', <function bar at 0x15355f0>), ('foo', <function foo at 0x13a2930>)]

Re: Wie getattr() auf selbem Modul aufrufen als Dispatcher?

Verfasst: Donnerstag 24. Februar 2011, 21:08
von Hyperion
Ah... danke!

Wobei ich inspect jetzt eher umständlich finde. Es soll ja grad schön kurz und kompakt sein.

So find ich es ganz hübsch:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import __main__

def foo():
    return "foo"

def bar():
    return "bar"

def usage():
    return "Usage:\n\t./script.py foo|bar"

if __name__ == "__main__":
    print getattr(__main__, sys.argv[1], usage)()

Re: Wie getattr() auf selbem Modul aufrufen als Dispatcher?

Verfasst: Donnerstag 24. Februar 2011, 21:30
von Defnull
Oder noch einfacher:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys

def foo():
    return "foo"

def bar():
    return "bar"

def usage():
    return "Usage:\n\t./script.py foo|bar"

if __name__ == "__main__":
    print globals().get(sys.argv[1], usage)()

Re: Wie getattr() auf selbem Modul aufrufen als Dispatcher?

Verfasst: Donnerstag 19. Juni 2014, 10:10
von silver0346
Hallo zusammen,

ich stehe vor der gleichen Aufgabe wie Hyperion: In Abhängigkeit von gegebenen Strings sollen Funktionen aufgerufen werden. Bisher hatte ich diese Funktionen in eine eigene Klasse ausgelagert. Da funktioniert getattr() zufriedenstellend. Wenn ich diese Funktion in die eigentliche Klasse verschiebe findet getattr() sich nicht zurecht.

Mein Testcode:

Code: Alles auswählen

import __main__

class TestGetattr(object):
    def __init__(self):
        super(TestGetattr, self).__init__()

    def get_1(self):
        print('get_1')

    def get_2(self):
        print('get_2')

    def main(self):
        calls = [1, 2]
        for _item in calls:
            print(_item)
            _fkt = 'get_' + str(_item)
            _call = getattr(__main__, _fkt)
            _call()

if __name__ == '__main__':
    m = TestGetattr()
    m.main()
Ergebnis ist:

Code: Alles auswählen

Traceback (most recent call last):
  File "C:/workspace/python/fill/test_getattr.py", line 23, in <module>
    m.main()
  File "C:/workspace/python/fill/test_getattr.py", line 18, in main
    _call = getattr(__main__, _fkt)
AttributeError: 'module' object has no attribute 'get_1'
1
An welcher Stelle liegt denn mein Denkfehler?

Vielen Dank im Voraus.

Re: Wie getattr() auf selbem Modul aufrufen als Dispatcher?

Verfasst: Donnerstag 19. Juni 2014, 10:16
von BlackJack
@silver0346: Zähl doch mal die Attribute auf die das *Modul* hat. Glaubst Du tatsächlich das *Modul* hat ein `get_1`-Attribut?

Edit: Deine Vermutung(en) kannst Du mit der `dir()`-Funktion auch gleich gegenprüfen.

Re: Wie getattr() auf selbem Modul aufrufen als Dispatcher?

Verfasst: Donnerstag 19. Juni 2014, 10:52
von silver0346
Sorry,

ich hab noch etwas weiter rumprobiert. self hat get_x. :oops:

Vielen Dank. Paßt in die Geschichte mit dem offenen Brief aus http://www.python-forum.de/viewtopic.php?f=1&t=23839