Packageinterne Importe bei Aufruf von außen

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
yaem
User
Beiträge: 8
Registriert: Sonntag 19. Juni 2011, 21:52

Schon wieder eine Anfängerfrage...
Ich hab ein Problem mit packages. Ich habe ein Verzeichnis namens "package" mit einer leeren "__init__.py" und zwei Modulen "one.py" und "two.py":

one.py:

Code: Alles auswählen

import two

def say(what):

  print("One says: ", what)
  two.say(what)
  

two.py:

Code: Alles auswählen

def say(what):

  print("Two says: ", what)

Im gleichen Ordner in dem auch "package" liegt hab ich eine "main.py":

Code: Alles auswählen

import package.one

package.one.say("hello")
Fehlermeldung:
> "python" "D:\Dokumente und Einstellungen\Me\Eigene Dateien\Programming\Applications\Python\Test\main.py"
Traceback (most recent call last):
File "D:\Dokumente und Einstellungen\Me\Eigene Dateien\Programming\Applications\Python\Test\main.py", line 1, in <module>
import package.one
File "D:\Dokumente und Einstellungen\Me\Eigene Dateien\Programming\Applications\Python\Test\package\one.py", line 1, in <module>
import two
ImportError: No module named two
"two.py" kann also scheints nicht gefunden werden. Wenn ich aber direkt die Datei "one.py" um die Zeile "say("hello")" ergänze und ausführe klappts wunderbar. Wo liegt mein Fehler?
BlackJack

@yaem: Ich nehme mal an Du startest den Test dann innerhalb von ``./package/`` — dann ist das Verzeichnis das aktuelle Arbeitsverzeichnis und das ist in `sys.path` enthalten. Wenn Du `main.py` oberhalb von ``./package/`` startest, dann ist `two.py` nicht im aktuellen Arbeitsverzeichnis, kann mit ``import foo`` also auch nicht gefunden werden. Du musst das entweder absolut oder relativ importieren. Ich bevorzuge absolut. Also ``from package import two``.
yaem
User
Beiträge: 8
Registriert: Sonntag 19. Juni 2011, 21:52

Mmh... Um Misverständnissen vorzubeugen, meine Verzeichnisstruktur sieht so aus:

main.py
package/
--> __init__.py
--> one.py
--> two.py

Ich habe jetzt mal in "one.py" anstatt "import two" "from package import two" geschrieben. Jetzt kann ich zwar "main.py" wie erwartet ausführen, allerdings vermeldet "one.py" beim direkten Ausführen logischerweise, dass ein Package namens "package" nicht existiert.
Die dritte Möglichkeit "from . import two" gibt dagegen die interessante Meldung: "ValueError: Attempted relative import in non-package"
Warum? "one.py" ist doch, dank __init__.py, eindeutig in einem package und müsste das doch auch erkennen?!?
Rein von der Logik her muss doch auch "import two" gehen, oder?
Vor allem beunruhigt mich, dass "from . import two" diese seltsame Fehlermeldung ausgiebt... Hab ich da wieder in meinem Editor was falsch eingestellt?!?


Ich möchte, dass "one.py" sozusagen die Zugriffschnittstelle für das package "package" ist und alle weiteren Module "two.py..." vor dem Benutzer des Packages verborgen bleiben.
BlackJack

@yaem: Das ist nur logisch wenn Du vorher in das Package-Verzeichnis hinein wechselst. Wenn Python das Package finden kann, dann kannst Du auch das Modul in dem Package direkt ausführen.
yaem
User
Beiträge: 8
Registriert: Sonntag 19. Juni 2011, 21:52

Häng ich da etwa zu sehr in meinem C/C++ Denken fest? Wenn da irgendein Header "#include "./another.h"" verlangt würde doch als allererstes im Verzeichnis des Headers gesucht werden. Bei Python ist das nicht so?
Wenn Python das Package finden kann, dann kannst Du auch das Modul in dem Package direkt ausführen.
Ich bin mir nicht sicher, ob ich verstehe, was du da sagst.
Die Varianten(in "package/one.py")...

"from package import two" und
"from . import two"

...funktionieren, wenn "one.py" über "main.py" ausgeführt wird. Aber dann nicht, wenn ich Code (zum Beispiel zu Testzwecken) direkt im Modul ausführe.
Da geht dann nur....

"import two"

Gibt es eine Möglichkeit beide Fälle - also direktes Ausführen im Modul und ausführen über Import - zu verbinden?

Gut, auf alle Fälle schein ich erstmal unbefriedigend um das Problem herumzukommen... Ich danke Dir! :)
BlackJack

Wenn Du den relativen import versuchst, dann wird geschaut das `.` das Paket `package` ist, aber dieses Paket gibt es nicht im Sinne von: es kann nicht mit ``import package`` importiert werden. Wäre ja komisch/inkonsistent wenn das relativ ginge, absolut aber nicht. ``from package import two`` funktioniert auch wenn Du `one.py` direkt ausführst *solange `package` importierbar ist*! Geh mal in das Verzeichnis wo `main.py` liegt und führe `one.py` *von dort aus* aus.
Antworten