Problem mit kleinem Modulsystem!

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Mittwoch 8. November 2006, 11:38

Hallo.

Ich bin grad dabei ein kleines Modulsystem zu schreiben.

Klappt glaub ich soweit ganz gut jedoch kommt da eine Fehlermeldung, mit der ich überhaupt nichts anfangen kann.

Code: Alles auswählen

Traceback (most recent call last):
  File "start.py", line 24, in ?
    get_modules()
  File "start.py", line 20, in get_modules
    return mod_function, mod_functions_name, modulelist, path
UnboundLocalError: local variable 'mod_function' referenced before assignment

Hier der Code, für das Modulsystem:

Code: Alles auswählen

#!/usr/bin/env python

import cherrypy
import os

def get_modules():
    path = os.path.join(os.curdir, 'modules')
    mod_zaehler = 0
    modulelist = []
    for module in os.listdir(path):
        modulelist.append(module)

        for modules in modulelist[mod_zaehler]:
            if 'expose' in dir(modules):

                for exposed in dir('expose'):
                    mod_functions_name = exposed.func_name
                    mod_function = exposed
                    mod_zaehler += 1
    return mod_function, mod_functions_name, modulelist, path

### Mainfunction #####

get_modules()

print 'mod_function = %s' % mod_function
print 'mod_function_name = %s' % mod_function_name
print 'modulelist = %s' % modulelist
print 'path = %s' % path
Es ist warscheinlich nicht die Beste Möglichkeit aber so dürfte es eigentlich funktionieren, wenn der Fehler weg währe.

Könnt Ihr mir helfen?

MfG EnTeQuAk

EDIT:
im Ordner '' /modules/ ''
sind bei mir zwei Testmodule mit folgendem Inhalt:

Code: Alles auswählen

class TestModul:
    def index(self):
        return 'Hallo Testmodu'
    expose = [(index2, 'testIndex')]
und Testmodu2

Code: Alles auswählen

class TestModul2:
    def index2(self):
        return 'Hallo Testmodu2'
    expose = [(index2, 'testIndex2')]
:D
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Mittwoch 8. November 2006, 12:00

Wie die Fehlermeldung schon (fast) sagt: Du greifst (lesend) auf eine Variable zu, die vorher nicht definiert wurde. Wenn du dir die betroffene Funktion nochmal genau ansiehst wirst du feststellen, dass die Variable nur innerhalb von if-Bedingung und drei Schleifen mit einem Wert belegt (und damit überhaupt deklariert und initialisiert) wird - was ja keineswegs immer der Fall ist. Mit einem Default-Wert zu Beginn der Funktion kannst du dem Abhilfe schaffen. Aber macht das so überhaupt wirklich Sinn?
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Mittwoch 8. November 2006, 13:04

Oki bin grad dabei alles einzeln auszutesten...

es klappt fast gar nichts ;)

Ich habe nun den Code:

Code: Alles auswählen

path = os.path.join(os.curdir, 'modules')
mod_zaehler = 0
modulelist = []
for module in os.listdir(path):
    modulelist.append(module.strip('.py'))
for module in modulelist:
    #__import__(module)  Das ist das Ziel des ganzen ;)
    print module
Das gibt nun folgendes aus:

Code: Alles auswählen

test
test2
__init__.pyc
__init__
Wie kann ich die Datei '' __init__.py '' komplett rausfischen. Die brauch ich nicht, ist aber fürs Importieren nötig (wenn cih da richtig aufgepasst habe)


MfG EnTeQuAk
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Mittwoch 8. November 2006, 14:49

Hi

So?

Code: Alles auswählen

modulelist1 = [modul[:-3]
                for modul in os.listdir(path)
                    if not modul.startswith('__init__.')
                        and not modul.endswith('.pyc')
                        and modul.endswith('.py')]
modulelist2 = []
for modul in os.listdir(path):
    if not modul.startswith('__init__.') and not modul.endswith('.pyc') and modul.endswith('.py'):
        modulelist2.append(modul[:-3])
Version 1 mit List Comprehension (oder wie man das auch imemr schreibt) und Version 2 genau gleich einfach mit einer normalen For-Schleife.

Gruss

PS & edit:
strip ist nicht die funktion die du willst, lese mal die doku darüber
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Mittwoch 8. November 2006, 15:33

So funktioniert es ;)

Danke erstmal!

Aber warum genau ist '' strip '' nicht das, was ich brauche. Selbst laut der Doku bin ich der Meinung, das ich es nicht direkt falsch gebrauche.

Jetzt komme ich zur letzte Hürde, die nicht ganz hinhaut.

Habe das nun so gemacht:

Code: Alles auswählen

import os

path = os.path.join(os.curdir, 'modules')
modulelist = []

def get_modules(path):
    mod_zaehler = 0
    for module in os.listdir(path):
        if not module.startswith('__init__.') and not module.endswith('.pyc') and module.endswith('.py'):
            modulelist.append(module.strip('.py'))
    return modulelist


get_modules(path)
mod_zaehler = 1
for module in modulelist:
    print 'Modul nummer: %d, was importiert wird, ist %s' %(mod_zaehler, module)
    mod = __import__(module)
    mod_zaehler+=1
folgendes wird ausgegeben:

Code: Alles auswählen

Modul nummer: 1, was importiert wird ist test2
Traceback (most recent call last):
  File "start.py", line 22, in ?
    mod = __import__(module)
ImportError: No module named test2
So. Scheint eigentlich alles zu klappen. Nur bin ich verdutzt, über den Importfehler bei '' test2 ''.
Er findet das Modul '' test2 '' kann es aber nicht importieren. Verstehe ich das richtig?

Wo liegt hier der Fehler?

MfG EnTeQuAk
BlackJack

Mittwoch 8. November 2006, 16:04

EnTeQuAk hat geschrieben:Aber warum genau ist '' strip '' nicht das, was ich brauche. Selbst laut der Doku bin ich der Meinung, das ich es nicht direkt falsch gebrauche.

Code: Alles auswählen

In [67]: 'python_happy.py'.strip('.py')
Out[67]: 'thon_ha'
Falls das nicht das ist, was Du erwartet hättest, solltest Du die Doku nochmal lesen. ;-)
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Mittwoch 8. November 2006, 16:11

*hust*

oki... habs nur oberflächlich gelesen :D

Gut. Oke... ich such mir da was anderes.

Ne Idee mit module.endswith hat auch net geklappt ;)

Na ja... aber das ist nicht das Hauptproblem.


MfG EnTeQuAk
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Mittwoch 8. November 2006, 16:22

Schau dir mal glob.glob() und die darin aus fnmatch verwendeten Pattern an, dann könntest du dir manuelles Filtern sparen.
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Mittwoch 8. November 2006, 22:55

Hi

Überlege mal genau was du importieren willst.

Wenn du es von Hand machst schreibst du auch nicht import test2 sondern import modules.test2. Daher kann __import__(module) nicht gehen ...

Hier ein auszug aus der Doku:
__import__(name[, globals[, locals[, fromlist[, level]]]])

For example, the statement "import spam" results in the following call: __import__('spam', globals(), locals(), [], -1); the statement "from spam.ham import eggs" results in "__import__('spam.ham', globals(), locals(), ['eggs'], -1)". Note that even though locals() and ['eggs'] are passed in as arguments, the __import__() function does not set the local variable named eggs; this is done by subsequent code that is generated for the import statement. (In fact, the standard implementation does not use its locals argument at all, and uses its globals only to determine the package context of the import statement.)

Also wirst du sowas brauchen:
m = __import__("modules", globals(), locals(), [module])

Nacher kannst du mit m.funktion_vom_modul() darauf zugreifen.

Gruss
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Donnerstag 9. November 2006, 13:43

Wunderbar, soweit habe ich nicht gedacht.


Funktioniert auch soweit.

Danke!!

Allerdings ist es doof ,das ganze in der Variablen ' m ' zu speichern, da ich teils mehr als 5 Module importiere.

Bedeutet, das ich dann, mal angenommen in 2 Modulen existiert eine Funktiion '' index() ''... nicht mal angenommen, das funktioniert so nicht.

Kann ich das ganze auch via

Code: Alles auswählen

__import__("modules", globals(), locals(), [module])
importieren?

(is nur ne Frage, da ich hier in der Schule bin kann ich es nicht austesten)



MfG EnTeQuAk
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Donnerstag 9. November 2006, 13:51

Hi

__import__ gibt dir das importierte Modul zurück, wenn du dies in keiner Variable speicherst kannst du nicht darauf zugreifen. Kannst natürlich auch die Module in eine Liste speichern.

Gruss
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Freitag 10. November 2006, 11:30

Vielleicht hilft dir dieser Schnipsel von meinem Code-Dachboden weiter:

Code: Alles auswählen

import os

import your.project.plugins


def get_available_plugins():
    """Return the names of available plugins.

    Search the plugin directory for filenames that start with 'Plugin' and
    have one of the following suffixes:
      '.py'  (Python source code)
      '.pyc' (Python byte code)
      '.pyo' (Python optimized byte code)
    The string embraced by said prefix and suffixes is the plugin name.
    Found plugin names will be returned as list, with duplicates removed.
    """
    path = your.project.plugins.__path__[0]
    plugins = []
    match_fn = re.compile('^Plugin(\w+)\.py[co]?$').search
    for item in os.listdir(path):
        if os.path.isfile(os.path.join(path, item)):
            match = match_fn(item)
            if match:
                plugins.append(match.group(1))
    plugins = list(Set(plugins))  # Remove duplicates.
    return plugins
Sowie:

Code: Alles auswählen

class PluginPool(dict):
    """A pool of available plugins.

    Contains plugins with their names as keys and their instances as values.
    Methods may raise KeyError if a bad key is used.
    """

    def add(self, name):
        """Import, instanciate and add the plugin or log the error.

        Existing plugin instances will be overwritten.
        """
        package = 'your.project.plugins'
        try:
            module = __import__('%s.%s' % (package, name), (), (), [''])
        except ImportError:
            log.error('%s plugin not found.' % name)
        except Plugin.PluginRequirementsNotFulfilled, msg:
            log.error('%s plugin does not fulfill all requirements: %s' \
                % (name, msg))
        else:
            self[name] = module.__dict__[name]()

# [...]
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Samstag 11. November 2006, 10:27

:D Bistn Schatz ;)

Klappt soweit. Habs ausprobiert. Der "einfachheit" Halber hab ich aber doch noch einen anderen Weg eingeschlagen.

Dieser funktioniert nun auch.

Habe sämtliche Module in einer separaten Modul-Datei gespeichert. So brauch ich sie nur noch auslesen. Der Vorteil ist, das man da auch verschiedene Andere Sachen speichern kann, was mit diesem Modulimport etwas komplizierter geworden wäre.

MfG EnTeQuAk
Antworten