Modul in anderem Projekt importieren oder direkt ausführen

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
berndx
User
Beiträge: 3
Registriert: Montag 9. September 2013, 20:40

Hallo liebes Forum,

ich programmiere schon einige Zeit in Python, komme aber an dieser Stelle nicht weiter.

Und zwar möchte ich ein Modul direkt aufrufen, es aber auch in anderen Projekten importieren.

Komischerweise funktioniert das in Python 2.7, aber in 3.2 nicht, sondern nur eine der beiden Varianten.

Um jetzt mal konkret zu werden hier ein einfaches Beispiel:

py_testpaket
|- test.py

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from paket import tools
from paket import modul

i = tools.random_int()

print("Zahl 1: " + str(i))
py_testpaket/paket
|- __init__.py (leer)
|- modul.py
|- tools.py

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
paket.modul

Test-Modul
"""

from . import tools

i = tools.random_int()

print("Zahl: " + str(i))

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
paket.tools

Test-Modul
"""

import random as r

def random_int():
	i = r.randint(0, 100)
	return i
Funktioniert wunderbar, wenn ich test.py aufrufe:

Code: Alles auswählen

$ python3 test.py 
Zahl: 68
Zahl 1: 73
Nur wenn ich jetzt modul.py direkt im Ordner /paket ausführe kommt dieser Fehler:

Code: Alles auswählen

$ python3 modul.py
Traceback (most recent call last):
  File "modul.py", line 10, in <module>
    from . import tools
ValueError: Attempted relative import in non-package
Ändert man nun die Zeile 10 in modul.py zu "import tools", kann ich es im selben Ordner ausführen:

Code: Alles auswählen

$ python3 modul.py
Zahl: 39
Aber test.py funktioniert nicht mehr:

Code: Alles auswählen

$ python3 test.py 
Traceback (most recent call last):
  File "test.py", line 5, in <module>
    from paket import modul
  File ".../py_testpaket/paket/modul.py", line 10, in <module>
    import tools
ImportError: No module named tools
Der Interpreter sucht tools.py im selben Ordner wie test.py.

Bei dem Modul, an dem ich arbeite, verwende ich Sphinx für die Dokumentation, wo die Funktionen mit Docstrings ausgelesen werden und Unittests mit nose, wo auch das Modul importiert werden muss. Diese sollen natürlich im selben Ordner liegen und nicht darüber. Außerdem hab ich eine demo.py, die verschiedene Funktionen zeigt und dafür auch aus dem gleichen Ordner das Modul importieren muss.

Ich schätze das ist ganz einfach zu lösen.
Wie mache ich es richtig?
BlackJack

@berndx: Das ist im Grunde nicht einfach zu lösen sondern gar nicht. Du versuchst da etwas zu machen was man nicht machen sollte: Ein Modul in einem Paket auszuführen als wenn es nicht im Paket wäre. Statt ``python3 modul.py`` innerhalb des Pakets auszuführen, ohne dass das *Paket* im Pfad liegt, funktioniert halt nicht. Gehe ein Verzeichnis höher und führe ``python3 ./paket/modul.py`` aus.
berndx
User
Beiträge: 3
Registriert: Montag 9. September 2013, 20:40

Danke für deine Antwort.

Ich befinde mich im Ordner py_testpaket und bekomme immer noch einen Fehler:

Code: Alles auswählen

$ python3 ./paket/modul.py
Traceback (most recent call last):
  File "./paket/modul.py", line 10, in <module>
    from . import tools
ValueError: Attempted relative import in non-package
Kannst du mir als Beispiel ein Python3-Paket empfehlen, dass aus mehreren Modulen besteht, die auch Funktionen aus anderen Modulen benutzen, wo es richtig und gut gemacht wird?
BlackJack

@berndx: Okay, sorry. Dann ``python3 -m paket.modul``. Das habe ich gerade eben selbst ausprobiert.
berndx
User
Beiträge: 3
Registriert: Montag 9. September 2013, 20:40

Das Funktioniert.

Wenn ich jetzt, als praktisches Beispiel, Unittests für modul.py schreiben will, hab ich bisher im Ordner /paket eine test_modul.py anlegen mit den Tests drin.
Da hätte ich dann wieder das Problem, dass der Import nicht funktioniert. (bisher hatte ich alles in einer Datei, da war das kein Problem)

Mein Repository würde hierbei den Ordner paket umfassen. Würde es Sinn machen, das eigentliche Python-Paket in einen eigenen Ordner zu packen und Tests sowie Doku etc im darüberliegenden Ordner?

Bei Flask wird es z.B. so gemacht und die Jungs von pocoo kann man wohl als gutes Vorbild nehmen.
https://github.com/mitsuhiko/flask
BlackJack

@berndx: Das Python-Paket in einen eigenen Ordner und Sachen wie Doku *über* diesem Ordner? Nein. Das wird bei Flask doch auch nicht gemacht. Aber so wie es bei Flask gemacht wird, macht es durchaus Sinn. Da ist das Paket auf der gleichen Ebene wie die Unterverzeichnisse für Dokumentation, Beispiel, und so weiter.

Wo man die Tests liegen hat ist ein wenig Geschmackssache. Es gibt Leute die haben sie lieber in einem Extrapaket welches nicht mit installiert wird, und andere packen sie in das Paket mit dem Rest des Programms, Rahmenwerks, oder der Bibliothek. Dann werden die Tests immer mitinstalliert und jeder kann bei seiner Installation auch die Tests mal laufen lassen. Flask hat die Tests in der normalen Paketstruktur.

Es kann auch Gründe geben beides zu machen. Also zum Beispiel das man besonders aufwändige Tests, die vielleicht grössere Mengen an Daten benötigen, in ein eigenes Paket auslagert, aber trotzdem welche ohne solche Abhängigkeiten mit in der normalen Paketstruktur ablegt.
Antworten