Seite 1 von 1
import Rätsel...
Verfasst: Samstag 7. November 2015, 16:01
von mutetella
Ich habe folgende Struktur:
Code: Alles auswählen
any_app/
:...core/
:... __init__.py
:... main.py
:... utils/
:... __init__.py
:... utility.py
main.py:
utility.py:
1. Wo ist ``main``?
Code: Alles auswählen
>>> import any_app.core
>>> dir(any_app.core)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__']
2. Warum?
Code: Alles auswählen
>>> from any_app.core import main
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "any_app/core/main.py", line 1, in <module>
from any_app.utils import utility
File "any_app/utils/utility.py", line 1, in <module>
from any_app.core import main
ImportError: cannot import name main
Re: import Rätsel...
Verfasst: Samstag 7. November 2015, 16:35
von __deets__
Die Namen welche in any_app.core verfuegbar sind wird durch dessen __init__.py bestimmt. Da wird nicht magisch main importiert.
Wenn du das machen willst, musst du ein
in selbiges __init__.py schreiben, und dann hast du das verfuegbar. So geht auch os vor, um os.path schon gleich anzubieten. Da ist das etwa komplizierter, aber das Prinzip ist das gleiche.
Was du *nicht* tun solltest, auch wenn es in Python2.x geht, ist "import main". Denn das ist ein relativer Import, und die sind Pfui, und das funktioniert auch nicht mehr, wenn man "from __future__ import absolute_import" angibt - aus gutem Grund.
Re: import Rätsel...
Verfasst: Samstag 7. November 2015, 17:31
von mutetella
@__deets__
Eben nicht. Auch wenn ich in der ``any_app.core.__init__.py`` ein
ausführe, bekomme ich
Code: Alles auswählen
>>> from any_app.core import main
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "any_app/core/__init__.py", line 1, in <module>
import any_app.core.main as main
File "any_app/core/main.py", line 1, in <module>
from any_app.utils import utility
File "any_app/utils/__init__.py", line 1, in <module>
import any_app.utils.utility as utility
File "any_app/utils/utility.py", line 1, in <module>
from any_app.core import main
ImportError: cannot import name main
Re: import Rätsel...
Verfasst: Samstag 7. November 2015, 17:46
von BlackJack
@mutetella: Ich denke __deets__ ging davon aus das es hier nur um die Verzeichnisshierarchie ging und nicht zusätzlich in den Modulen noch zirkuläre Importe bestehen. Die macht man nämlich unter anderen genau aus diesem Grund nicht.
Re: import Rätsel...
Verfasst: Samstag 7. November 2015, 18:05
von __deets__
Tatsaechlich geht es nicht so, wie ich das dachte. Sieh Code unten.
Die einzige Begruendung dafuer, die ich mir vorstellen kann ist, dass waehrend "any_app.core" als Modul definiert wird, soll durch einen import schon darauf Bezug genommen werden. Das muss natuerlich fehlschlagen. Aber einen eleganten Weg, ohne relative Importe doch ein komplettes Paket/Modul in den Namensraum zu hieven habe ich nicht gefunden - soll vielleicht nicht sein - oder, sonst wer einen Idee?
@BlackJack: deinen zirkulaeren import Bezug verstehe ich nicht ganz - wer zirkelt wo?
Code: Alles auswählen
import sys
import os
import shutil
basedir = sys.argv[1]
if os.path.exists(basedir):
shutil.rmtree(basedir)
os.mkdir(basedir)
files = {
("any_app", "__init__.py") : "",
("any_app", "core", "__init__.py") : """
import main # geht, aber pfui. Nur was sonst?
from .main import main_func # geht
#import any_app.core.main as main # geht nicht
""",
("any_app", "core", "main.py") : """
def main_func():
print "main_func"
""",
}
for path, content in files.iteritems():
destpath = basedir
for part in path[:-1]:
destpath = os.path.join(destpath, part)
if not os.path.exists(destpath):
os.mkdir(destpath)
destfile = os.path.join(destpath, path[-1])
with open(destfile, "wb") as outf:
outf.write(content)
sys.path.append(basedir)
import any_app.core.main
Re: import Rätsel...
Verfasst: Samstag 7. November 2015, 18:17
von kbr
@__deets__: main.py und utility.py importieren sich gegenseitig. So was geht schief.
Re: import Rätsel...
Verfasst: Samstag 7. November 2015, 18:47
von mutetella
Ok, ich hab' unter anderem noch
diesen Beitrag auf google groups gefunden, der mein Problem widerspiegelt. Wenn ich das richtig verstehe, dann liegt mein Problem hier:
If a module does exist in sys.modules then an import simply returns that
module whether or not it has completed executing. That is the reason why
cyclic imports may return modules which appear to be partly empty.
Jetzt könnte ich natürlich folgende Änderung machen:
``any_app/core/main.py``
Code: Alles auswählen
#from any_app.utils import utility
import any_app.utils
``any_app/utils/utility``
Dadurch umgehe ich zwar das Problem, erzeuge aber so einen Wahnsinn (das ist doch jetzt ein circular import, oder?):
Code: Alles auswählen
>>> from any_app.core import main
>>> dir(main.any_app)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', 'core', 'utils']
>>> dir(main.any_app.core)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', 'main']
>>> dir(main.any_app.core.main)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'any_app']
>>> dir(main.any_app.core.main.any_app)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', 'core', 'utils']
Ist das ganze hier vielleicht mit ein Beispiel für das, was ich in
Gründe für import innerhalb Funktion? angesprochen hatte?
Und jetzt natürlich die Frage: Wie lässt sich das lösen?
Re: import Rätsel...
Verfasst: Samstag 7. November 2015, 18:58
von BlackJack
@mutetella: Das ist eigentlich kein Grund für einen ``import`` in einer Funktion sondern ein Grund keine zirkulären importe zu machen. Dein `main` braucht `utility` und `utility` braucht `main`? Warum? Wenn sich zwei Module gegenseitig brauchen, dann stellt sich die Frage warum das dann überhaupt zwei Module sind wenn die so eng zusammenhängen. Den Namen nach würde ich sagen dürfte `utility` das `main`-Modul nicht benötigen. Das löst man normalerweise in dem man das was beide Module brauchen in ein drittes Modul auslagert um den zirkulären Import loszuwerden.
Re: import Rätsel...
Verfasst: Samstag 7. November 2015, 19:24
von mutetella
@BlackJack
Ich habe ein ``core`` package, das neben dem ``main`` module auch ein ``dt`` module enthält, in dem sich Klassen befinden, die ich sowohl in ``main`` als auch in ``utils`` verwende. Und diverse Funktionen aus ``utils`` wiederum verwende ich in ``main``. Selbst wenn ich diese Klassen in ein anderes Modul auslagern würde, wäre damit das Problem nicht gelöst? Dann würde ich doch nur dieses neue Modul wiederum in ``main`` und ``utils`` importieren müssen.
Und: Weshalb habe ich das Problem erst, seitdem ich meine Module innerhalb packages thematisiert habe?
Re: import Rätsel...
Verfasst: Samstag 7. November 2015, 19:29
von mutetella
EDIT:
Oh Mann, ich blicke bald selbst nicht mehr durch...

:
Ich habe ein Modul `utils/utils.py`, das auf Klassen aus `core/dt.py` zugreift. Und `core/dt.py` wiederum verwendet Hilfsfunktionen aus `utils/utils.py`. Das ist das Problem...
Re: import Rätsel...
Verfasst: Samstag 7. November 2015, 20:21
von Sirius3
@mutetella: da sieht man mal wieder, dass es kein Problem ist, dass es keine zirkulären Importe gibt, sondern dass diese Einschränkung hilft, gut strukturierten Code zu schreiben. Am besten versuchst Du mal, Deine Abhängigkeiten mit Papier und Bleistift zu entwirren.
Re: import Rätsel...
Verfasst: Samstag 7. November 2015, 20:30
von mutetella
@Sirius3
Offensichtlich, ja. Allerdings verstehe ich noch nicht, weshalb das Problem erst auftrat, nachdem ich meine Module auf Packages verteilt habe.
Ohne Packages hatte ich:
`dt.py`:
`utils.py`:
Seit der Aufteilung in Packages:
`core/dt.py`:
`utils/utils.py`:
Wo genau liegt der Unterschied?
Re: import Rätsel...
Verfasst: Samstag 7. November 2015, 21:14
von snafu
mutetella hat geschrieben:Oh Mann, ich blicke bald selbst nicht mehr durch...

:
Das spricht nicht unbedingt dafür, dass deine derzeitige Strukturierung besonders hilfreich ist. Bevor man da jetzt an den Symptomen solange herumdoktert bis es irgendwie funktioniert, würde ich doch eher empfehlen, den kompletten Entwurf nochmal zu überdenken.
Re: import Rätsel...
Verfasst: Samstag 7. November 2015, 21:26
von mutetella
@snafu
Nun ja, ganz so dramatisch ist es jetzt auch wieder nicht... `utils` verwendet etwas aus meinem `dt` Modul und anderst 'rum... Jetzt, da ich weiß, wo das Problem liegt, lässt sich das sicher umgestalten. Und ich habe auch nicht vor, an den Symptomen herumzudoktern, allerdings muss ich jetzt auch nicht die gesamte Strukturierung in Frage stellen...
Vielmehr würde mich eine Antwort auf meine letzte Frage interessieren...