eval oder wie importiere ich ein modul per filename

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
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

Montag 13. Februar 2006, 15:39

Hallo, ich möchte module importieren, anhand einer liste von dateinamen.

Da "import file" nicht einfach geht, muss ich eval einsetzen glaube ich.

Das da unten funktioniert aber nicht - warum ?

Code: Alles auswählen

for filebase in os.listdir("."):                    
    eval ("import " +  x)
danke für eure hilfe
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

Montag 13. Februar 2006, 15:50

hat sich erledigt.

soweit ich das sehe ist

Code: Alles auswählen

exec ("import %s" %filebase)
der einzige weg, da import ein keyword ist. Oder ?
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Montag 13. Februar 2006, 17:12

Hi

Es geht auch mit:

Code: Alles auswählen

modul = __import__(filebase,globals(),locals(),[])
modul.funktionA(x,y,z)
Gruss

PS: beim Import den Namen und nicht der Dateiname angeben (Name ist ohne Endung)
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

Montag 13. Februar 2006, 19:01

Hey Danke, die Lösung gefällt mir viel besser !

was ist die leere liste am ende ?
Kannst du mir das __import__ noch ein bischen erklären ?
Finde leider keine Referenz dazu.

__import__(filebase,globals(),locals(),[])

1. = package
2 = globaler namespace den das modul kennt ?
3 = lokaler namespace ?
4 = ??

Auch würde ich gerne die hauptklasse instanzieren (heisst so wie die filebase). Als String funktioniert das schonmal nicht, muss ich da mit getattr arbeiten ?

Also das import gibt mir das modul zurück, nur wie kann ich die klasse instanzieren die wie filebase heisst ? Habe vieles probiert, geht aber nichts
:(
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Montag 13. Februar 2006, 22:36

Hi

Also gross genauer erklären kann ich es auch nicht wirklich. Hab mal noch ein wenig gesucht und folgendes gefunden:
After a quick check (in sys.modules) to see if the module has already been loaded, we use the built-in function __import__() to load the module we desire. You may notice something odd about the call to __import__(): why is the last parameter a list whose only member is an empty string? This hack stems from a quirk about __import__(): if the last parameter is empty, loading class "A.B.C.D" actually only loads "A". If the last parameter is defined, regardless of what its value is, we end up loading "A.B.C". Once we have "A.B.C", we use getattr() to reference the function (or class) within the module.
auf der Seite http://aspn.activestate.com/ASPN/Cookbo ... ipe/223972

und hier noch was
When the name argument contains a dot (when it specifies a submodule of a package), the fromlist argument is set to the list ['*'] so that the return value is the named module rather than the top-level package containing it as would otherwise be the case.

Soweit ich das Verstanden habe sollte der letzte Parameter ['*'] sein wenn es im Modulnamen einen . hat.

Und die Klasse solltest du mit

Code: Alles auswählen

mod.__getattribute__(filebase)
bekommen und dann einfach den Constructor aufrufen

mit z.B. leeren Klammern

Code: Alles auswählen

mod.__getattribute__(filebase)()
Gruss
BlackJack

Dienstag 14. Februar 2006, 00:03

Mad-Marty hat geschrieben:Finde leider keine Referenz dazu.
Interpreter laden und ``help(__import__)`` für eine Kurzfassung, ansonsten in der Doku bei den eingebauten Funktionen.
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 14. Februar 2006, 07:04

Mad-Marty hat geschrieben:__import__(filebase,globals(),locals(),[])

1. = package
2 = globaler namespace den das modul kennt ?
3 = lokaler namespace ?
4 = ??
Nr. 4 ist dazu da um gezielt ein Objekt aus der Datei zu holen. s.a. http://www.python-forum.de/viewtopic.php?t=3558

Mit andern Worten, wenn man from bla import blub machen will: __import__("bla",globals(),locals(),["blub"])

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Dienstag 14. Februar 2006, 07:57

Modul laden:

Code: Alles auswählen

sys = __import__('pocoo')
Ein Package laden:

Code: Alles auswählen

auth = __import__('pocoo.components.core.auth').components.core.auth
Package mit hilfe der Include List auflösen:

Code: Alles auswählen

auth = __import__('pocoo.components.core.auth', locals(), globals(), [''])
einzelne Klassen importieren:

Code: Alles auswählen

auth = __import__('pocoo.components.core.auth', locals(), globals(), ['']).User
Warum, wieso und überhaupt, steht im Import Hook PEP: http://python.org/peps/pep-0302.html
TUFKAB – the user formerly known as blackbird
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 14. Februar 2006, 08:19

blackbird hat geschrieben:

Code: Alles auswählen

auth = __import__('pocoo.components.core.auth').components.core.auth

Code: Alles auswählen

auth = __import__('pocoo.components.core.auth', locals(), globals(), ['']).User
Und was ist wenn "components.core.auth" bzw. "User" nur als String vorliegen? Dann braucht man den letzten Platzhalter "fromlist"! Ansonsten kann man auch das Module normal importieren :)

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

Dienstag 14. Februar 2006, 09:16

Danke für die vielen Antworten.

Jetzt habe ich, wie jens schon andeutete, das problem das der Klassenname nur als String vorliegt.

Und ich möchte, das der Module Namespaceverfügbar ist.


also in etwa so:

Code: Alles auswählen

for file in files:
    __import__(file,globals(),locals(),[])
das modul soll danach aber über
"mymodule"."myclass" ansteuerbar sein, da ich versuche plugins zu laden müssen die klassen des moduls erreichbar sein mittels "file.class_a".

(Primär, muss das Modul seine eigenen klassen (z.b. MyException) kennen.)

from x import * ist ungünstig weil sich dann ja evtl manche klassen überschreiben könnten.


Hoffe das ist halbwegs verständlich was ich versuche ;-)


EDIT::
Probiert habe ich eben das:

Code: Alles auswählen

>>> dummystr = "dummy"
>>> sys.modules[dummystr] = __import__(dummystr,globals(),locals(),[])
>>> o = dummy.class1()
Traceback (most recent call last):
  File "<interactive input>", line 1, in ?
NameError: name 'dummy' is not defined
>>> import dummy
>>> o = dummy.class1()
Geht leider auch nicht wenn ich das in modules eintrage :(


EDIT2:

Hier ein test von c:\dummy.py, enthält die klasse dummy, und die klasse class1. Es funktioniert. Ob es die beste Lösung ist bezweifel ich aber, was meint ihr dazu ?

Code: Alles auswählen

>>> import sys
>>> sys.path.append("c:\\")
>>> dummystr = "dummy"
>>> sys.modules[dummystr] = __import__(dummystr,globals(),locals(), [])
>>> o = getattr(sys.modules.get(dummystr), dummystr)()
>>> o.getname()
'dummy'
>>> o.instanciate_class1()
class1
>>> 
Antworten