Zusammenfassung: Mit PyDev kann ich kein Python-Modul (FooTest) zum Importieren eines anderen (FooMock) in den gleichen (Test-) Quellordner bekommen.PyDev aus sekundären Quellordnern importieren
Ich habe zwei Quellordner und vier Python-Module, mit der Verzeichnisstruktur unten. Der minimale Beispielcode steht am Ende der Frage. Obwohl ich viele Informationen zur Verfügung gestellt habe, lassen Sie sich davon nicht einschüchtern - es ist ein einfaches Problemszenario.
PyDevProject/
src/ (source folder for prod code)
foo/
__init__.py
Bar.py
Foo.py
test/ (source folder for tests)
foo/
__init__.py
FooMock.py
FooTest.py
Das Problem hier ist, dass, wenn ich im FooTest Modul zu importieren FooMock Klasse versuchen, ich die folgende Fehlermeldung erhalten (PyUnit läuft die FooTest Tests ausführen):
Finding files... done.
Importing test modules ... Traceback (most recent call last):
File "/Applications/Eclipse.app/Contents/Eclipse/plugins/org.python.pydev_4.5.4.201601292234/pysrc/_pydev_runfiles/pydev_runfiles.py", line 468, in __get_module_from_str
mod = __import__(modname)
File "/Users/me/Development/krtiWorkspace/ImportTest/test/foo/FooTest.py", line 4, in <module>
from foo.FooMock import FooMock
ImportError: No module named FooMock
ERROR: Module: FooTest could not be imported (file: /Users/me/Development/krtiWorkspace/ImportTest/test/foo/FooTest.py).
done.
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
Dinge, die ich habe versucht:
- Obwohl FooMock und FooTest beide im selben Python-Paket sind, kann FooMock nicht importiert werden.
- Das Verschieben von FooMock in das Verzeichnis
src/
funktioniert, selbst wenn es unter einem eindeutigen Python-Paket platziert wird (solange es untersrc/
steht). Aber das ist für mich nicht akzeptabel (um Testcode in den Produktionsquellordnern zu haben). - Ich habe sichergestellt, dass die PYTHONPATH-Einstellungen in PyDev festgelegt sind, um anzugeben, dass beide Ordner Quellordner sind.
- Das Kopieren und Einfügen des FooMock-Codes in den FooTest-Code funktioniert. Aber das ist nicht akzeptabel für mich (da ich FooMock an anderer Stelle in mehreren Testdateien referenzieren möchte und ich nicht möchte, dass mehrere Kopien von FooMock konsequent herumschweben).
Kann ich irgendetwas dagegen tun?
Code:
# Code for Bar.py -----------------------------------------------------
class Bar(object):
def __init__(self, foo):
self.foo = foo
def next(self):
self.foo.incr()
# Code for Foo.py -----------------------------------------------------
class Foo(object):
def __init__(self):
self.num = 0
def incr(self):
self.num = self.num + 1
# Code for FooMock.py -------------------------------------------------
class FooMock(object):
def mock_incr(self):
self.hit = True
# Code for FooTest.py -------------------------------------------------
import unittest
from foo.Foo import Foo
from foo.Bar import Bar
from foo.FooMock import FooMock
class Test(unittest.TestCase):
def test_Foo(self):
foo = Foo()
foo.incr()
self.assertEquals(1, foo.num, "should be 1")
def test_Bar(self):
foo = FooMock()
bar = Bar(foo)
bar.next()
if __name__ == "__main__":
unittest.main()
Screenshot von Verzeichnis: Image showing directory structure and PYTHONPATH as previously explained
Das war das Problem! Hier nahm ich an, dass dies wie Java war. Anfängerfehler. Danke @Grepe. Um das zu bestätigen, hat das Umbenennen des Test/Foo-Pakets zu Test/Footest Python erlaubt, FooMock zu finden. –
Eine kleine Erweiterung zu meiner Frage: Müssen alle Python-Pakete eindeutig sein? I.e. Kann ich SRC/foo.bar und TEST/tests.foo.bar haben? Ich überprüfe jetzt auf jeden Fall. –
Sie können das Paket erweitern, nachdem Sie es in Ihren Code importiert haben (dies wird als "Affe-Patching" bezeichnet, siehe dieses SO-Thema zum Beispiel: http://stackoverflow.com/questions/5626193/what-is-a) -Monkey-Patch). aber die Art, wie der Import funktioniert, ist, dass er nach dem Paket in jedem der Verzeichnisse sucht, die in Ihrem PYTHONPATH in der Reihenfolge enthalten sind, und sobald es es findet, hört es dort auf. Wenn das Paket mehrere Male im Pfad ist, wird es nur beim ersten Mal eingeschlossen, und nur der Code aus dieser ersten Definition wird verwendet. – grepe