Import eines eigenen Moduls scheitert

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
Malachite
User
Beiträge: 34
Registriert: Sonntag 24. Juni 2012, 13:43
Wohnort: Berlin

Moin,
ich habe diese Verzeichnisstruktur:

Code: Alles auswählen

src
|-- __init__.py
|-- core.py
|-- output
    |-- __init__.py
    |-- base.py
    |-- svg.py
Mein Problem: In der svg.py soll eine Klasse aus der base.py importiert werden:

Code: Alles auswählen

from base import DrawBase
Leider scheint Python base nicht zu finden (ImportError). Alle anderen Imports funktionieren aber. Das ändert sich auch nicht, wenn ich base in der __all__-Liste von __init__.py notiere (was ich eigentlich nicht machen möchte, damit base nicht bei einem

Code: Alles auswählen

from output import *
importiert wird).

Wo ist das Problem?

EDIT: Wenn svg.py direkt ausgeführt wird (und nicht in core.py importiert), dann funktioniert es. Liegt es vielleicht daran, dass ich in core.py importlib.import_module() benutze? Ich dachte immer, diese beiden Zeilen bewirkten das Gleiche, aber offensichtlich ist es nicht so:

Code: Alles auswählen

import mod as name

name = importlib.import_module('mod')
Offenbar hat das mit import_module() importierte Modul einen anderen Geltungsbereich.

EDIT²:

Code: Alles auswählen

from .base import DrawBase
funktioniert auch. Aber damit kann man ja nur Komponenten des Moduls importieren, nicht das Modul selbst:

Code: Alles auswählen

import .base # SyntaxError
EDIT³: Ich glaube, Python hasst mich:

Code: Alles auswählen

# __init.py__
# ohne Docstrings, daher weichen Zeilenangaben in den Fehlermeldungen ab
__all__ = ['core', 'output']

from core import Graphic

# bpython3
# src ist das Programmverzeichnis
>>> import src
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "src/__init__.py", line 14, in <module>
    from core import Graphic
ImportError: No module named core
>>> 

anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Vielleicht helfen die absolute imports weiter:
http://www.python.org/dev/peps/pep-0328/
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Moin. Entsprechend dieser Beschereibung, sollte dies funktionieren

Code: Alles auswählen

from . import base
Malachite
User
Beiträge: 34
Registriert: Sonntag 24. Juni 2012, 13:43
Wohnort: Berlin

Relative Imports sind die mit dem Punkt vorne, richtig?

Ich versuche, meinen Code möglichst PEP8-konform zu schreiben, und relative Imports sind eher zu vermeiden, wenn ich das richtig gelesen habe. Außerdem sehe ich sie hier eher als Workaround und nicht als Lösung, weil das Problem nicht gelöst, sondern umgangen wird. Daher möchte ich sie nur einsetzen, wenn es wirklich nicht anders geht.

Das Komische ist: Entferne ich import_module() und ersetze es durch zig if/elif-Abfragen, funktionieren alle Imports. Ist das ein Bug oder ein Feature in import_module()?

Zum besseren Verständnis hier der betreffende Code:

Code: Alles auswählen

# core.py
from importlib import import_module

class Graphic():
    # […]
    def draw(self, fmt, *, drawAgain=False, **additional):        
        #[…]        
        try:
            drawModule = import_module('output.%s' % str(fmt))
        except ImportError:
            raise ValueError("Invalid format: %s" % str(fmt))
            return False
        else:
            # Could be nicer with a temporary var
            self._results[fmt] = drawModule.Draw(self._width, self._height,
                                                 self._actions, **additional
                                                 ).get()
            return self._results[fmt]

Antworten