1. Ziel des Tests
Das Ziel war, die Dobot-Python-API schrittweise zu testen und dabei die einzelnen Fehlerquellen sauber voneinander zu trennen:
- Läuft die verwendete Python-Version und stimmt die Architektur?
- Wird das SDK-Verzeichnis korrekt gefunden?
- Ist die Datei
DobotDll.dllvorhanden? - Kann
DobotDllType.pyals Python-Modul importiert werden? - Kann
DobotDllType.pyanschließend die DLL wirklich laden? - Erst danach: Kann eine Verbindung zum Dobot hergestellt werden?
2. Projektstruktur
Für die Tests wurde folgende Grundstruktur verwendet:
Dobot-Python/
├── dobot.py
├── sdk64/
│ ├── __init__.py
│ ├── DobotDllType.py
│ └── DobotDll.dll
└── api-testen/
├── start.py
└── test.py
Die Datei test.py liegt zwei Ebenen unterhalb von Dobot-Python. Deshalb liefert:
Path(__file__).resolve().parent
den Ordner api-testen, während:
Path(__file__).resolve().parent.parent
den Projektordner Dobot-Python ergibt.
projekte in den Python-Suchpfad aufnehmen“ war ungenau. Tatsächlich wird hier der Ordner Dobot-Python in sys.path aufgenommen.3. Ausgangspunkt: Test über dobot.py
Der erste Test verwendete:
from pathlib import Path
import sys
# Übergeordneten Ordner "Dobot-Python" in den Python-Suchpfad aufnehmen
PROJEKTORDNER = Path(__file__).resolve().parent.parent
if str(PROJEKTORDNER) not in sys.path:
sys.path.insert(0, str(PROJEKTORDNER))
import dobot
from sdk64 import DobotDllType as dType
api = dobot.init()
sys.exit()
Die Ausgabe zeigte:
Python-Version: 3.14.5
Python-Architektur: 64bit
SDK-Verzeichnis: D:\Github\andreas519.github.io\projekte\dobot_magician\Dobot-Python\sdk64
DLL-Datei: D:\Github\andreas519.github.io\projekte\dobot_magician\Dobot-Python\sdk64\DobotDll.dll
DLL vorhanden: True
FEHLER: Die serielle Schnittstelle COM10 ist nicht verfügbar.
Vom Betriebssystem erkannte COM-Ports:
COM13 USB-SERIAL CH340 (COM13)
Das Programm wird beendet.
Process ended with exit code 1.
Damit war bereits klar:
- Python läuft als 64-Bit-Version.
- Das SDK-Verzeichnis wird gefunden.
- Die DLL-Datei ist vorhanden.
- Die Verbindung scheitert zunächst an der seriellen Schnittstelle.
4. Woher kam COM10?
In start.py stand kein COM10. Die Ursache war der Aufruf:
import dobot
api = dobot.init()
Mit import dobot wird das Modul dobot.py geladen. Dort ist bzw. war COM10 als Standardwert für die Initialisierung hinterlegt.
Ein Aufruf ohne Argument:
api = dobot.init()
entspricht deshalb sinngemäß einem Aufruf wie:
api = dobot.init("COM10")
Der aktuelle Windows-Computer erkannte den angeschlossenen USB-Seriell-Wandler jedoch als:
COM13 USB-SERIAL CH340 (COM13)
Damit war der erste Fehler verstanden: dobot.init() erwartete COM10, tatsächlich war aktuell COM13 vorhanden.
5. Direkter Test von DobotDllType.py
Um dobot.py als zusätzliche Fehlerquelle auszuschließen, wurde ein direkter Test von DobotDllType.py vorbereitet.
Die Testdatei ermittelt zunächst die wichtigsten Pfade:
from pathlib import Path
import platform
import sys
PROJEKTORDNER = Path(__file__).resolve().parent.parent
if str(PROJEKTORDNER) not in sys.path:
sys.path.insert(0, str(PROJEKTORDNER))
sdk_verzeichnis = PROJEKTORDNER / "sdk64"
dll_datei = sdk_verzeichnis / "DobotDll.dll"
print("Python-Version: ", platform.python_version())
print("Python-Architektur:", platform.architecture()[0])
print("SDK-Verzeichnis: ", sdk_verzeichnis)
print("DLL-Datei: ", dll_datei)
print("DLL vorhanden: ", dll_datei.exists())
from sdk64 import DobotDllType as dType
print("DobotDllType.py: ", dType.__file__)
Die zusätzliche Ausgabe von dType.__file__ ist besonders nützlich. Sie zeigt exakt, welche Datei tatsächlich importiert wurde:
DobotDllType.py: D:\Github\andreas519.github.io\projekte\dobot_magician\Dobot-Python\sdk64\DobotDllType.py
DobotDllType.py konnte erfolgreich importiert werden.6. Unterschied: Python-Modul importieren und DLL laden
Diese beiden Schritte sind nicht dasselbe.
6.1 Python-Modul importieren
from sdk64 import DobotDllType as dType
Dadurch wird DobotDllType.py als Python-Modul geladen. Funktionen, Klassen und Konstanten stehen anschließend über dType zur Verfügung.
6.2 Die eigentliche DLL laden
api = dType.load()
Erst dieser Aufruf versucht, DobotDll.dll als native Windows-Bibliothek zu laden.
| Testschritt | Was wird geprüft? |
|---|---|
from sdk64 import DobotDllType as dType | Kann das Python-Modul importiert werden? |
dType.__file__ | Welche konkrete Datei wurde importiert? |
dType.load() | Kann die native DLL geladen werden? |
api = dType.load() auskommentiert ist, wird die DLL nicht geladen. Dann kann der Import von DobotDllType.py erfolgreich sein, obwohl das spätere Laden der DLL noch fehlschlägt.7. Der eigentliche DLL-Ladefehler
Mit aktiviertem Aufruf:
api = dType.load()
erschien:
Traceback (most recent call last):
File "...\api-testen\test.py", line 25, in <module>
api = dType.load()
File "...\sdk64\DobotDllType.py", line 460, in load
return CDLL("DobotDll.dll", RTLD_GLOBAL)
File "...\ctypes\__init__.py", line 451, in _load_library
return _LoadLibrary(self._name, winmode)
FileNotFoundError: Could not find module 'DobotDll.dll'
(or one of its dependencies).
Try using the full path with constructor syntax.
Das wirkte zunächst widersprüchlich, weil vorher ausgegeben wurde:
DLL vorhanden: True
7.1 Warum ist das kein Widerspruch?
Die Variable:
dll_datei = sdk_verzeichnis / "DobotDll.dll"
prüft nur, ob die Datei an diesem vollständigen Pfad vorhanden ist.
Die Funktion dType.load() verwendet diesen Pfad aber nicht. Laut Fehlermeldung führt DobotDllType.py aus:
return CDLL("DobotDll.dll", RTLD_GLOBAL)
Die DLL wird also nur anhand ihres Dateinamens gesucht:
DobotDll.dll
Das Verzeichnis sdk64 ist damit nicht automatisch Teil des Windows-DLL-Suchpfads.
test.py
│
├── findet:
│ D:\...\Dobot-Python\sdk64\DobotDll.dll
│
│ → DLL vorhanden: True
│
└── dType.load()
│
└── CDLL("DobotDll.dll")
│
└── sucht erneut nur nach dem Dateinamen
→ FileNotFoundError
8. Test mit os.add_dll_directory()
Für den nächsten Test wird das Verzeichnis sdk64 ausdrücklich in den Windows-DLL-Suchpfad aufgenommen.
dll_verzeichnis_handle = os.add_dll_directory(str(sdk_verzeichnis))
api = dType.load()
Die Funktion:
os.add_dll_directory(...)
registriert das angegebene Verzeichnis für die Suche nach DLLs.
Dieser Test verändert DobotDllType.py zunächst nicht. Damit kann geprüft werden, ob das Problem tatsächlich nur im DLL-Suchpfad liegt.
9. Vollständiges Testprogramm
Die folgende Version trennt die Schritte klar voneinander und gibt verständliche Statusmeldungen aus:
from pathlib import Path
import os
import platform
import sys
# Übergeordneten Ordner "Dobot-Python" in den Python-Suchpfad aufnehmen
PROJEKTORDNER = Path(__file__).resolve().parent.parent
if str(PROJEKTORDNER) not in sys.path:
sys.path.insert(0, str(PROJEKTORDNER))
sdk_verzeichnis = PROJEKTORDNER / "sdk64"
dll_datei = sdk_verzeichnis / "DobotDll.dll"
print("Python-Version: ", platform.python_version())
print("Python-Architektur:", platform.architecture()[0])
print("SDK-Verzeichnis: ", sdk_verzeichnis)
print("DLL-Datei: ", dll_datei)
print("DLL vorhanden: ", dll_datei.exists())
print()
# DobotDllType.py importieren
from sdk64 import DobotDllType as dType
print("DobotDllType.py: ", dType.__file__)
print()
print("DLL-Verzeichnis wird zum Windows-DLL-Suchpfad hinzugefügt ...")
# Das Verzeichnis sdk64 für die DLL-Suche registrieren.
# Das Handle muss während des Ladens der DLL erhalten bleiben.
dll_verzeichnis_handle = os.add_dll_directory(str(sdk_verzeichnis))
print("DLL-Verzeichnis registriert.")
print()
print("DobotDll.dll wird geladen ...")
try:
api = dType.load()
print("DobotDll.dll wurde erfolgreich geladen.")
print("API-Objekt:", api)
except Exception as fehler:
print()
print("FEHLER beim Laden der DobotDll.dll:")
print(type(fehler).__name__ + ":", fehler)
sys.exit(1)
print()
print("Test erfolgreich beendet.")
sys.exit()
Erwartete Ausgabe bei erfolgreichem Laden
Python-Version: 3.14.5
Python-Architektur: 64bit
SDK-Verzeichnis: D:\...\Dobot-Python\sdk64
DLL-Datei: D:\...\Dobot-Python\sdk64\DobotDll.dll
DLL vorhanden: True
DobotDllType.py: D:\...\Dobot-Python\sdk64\DobotDllType.py
DLL-Verzeichnis wird zum Windows-DLL-Suchpfad hinzugefügt ...
DLL-Verzeichnis registriert.
DobotDll.dll wird geladen ...
DobotDll.dll wurde erfolgreich geladen.
API-Objekt: <CDLL ...>
Test erfolgreich beendet.
10. Was bedeutet das Ergebnis?
Fall A: Die DLL wird erfolgreich geladen
Dann ist bewiesen:
- Python und DLL besitzen eine passende Architektur.
DobotDllType.pykann importiert werden.DobotDll.dllist grundsätzlich ladbar.- Das ursprüngliche Problem lag am DLL-Suchpfad.
Fall B: Es erscheint weiterhin FileNotFoundError
Dann kann eine Abhängigkeit der DLL fehlen. Die Fehlermeldung weist ausdrücklich darauf hin:
Could not find module 'DobotDll.dll' (or one of its dependencies).
In diesem Fall muss untersucht werden, ob DobotDll.dll weitere DLLs benötigt, die Windows nicht findet.
Fall C: Es erscheint ein Architekturfehler
Dann passen Python und DLL möglicherweise nicht zusammen, zum Beispiel:
- 64-Bit-Python mit 32-Bit-DLL oder
- 32-Bit-Python mit 64-Bit-DLL.
DobotDllType.py funktioniert. Der Fehler tritt erst beim Aufruf von dType.load() auf. Der nächste gezielte Test ist deshalb die Registrierung des Ordners sdk64 mit os.add_dll_directory().11. Mögliche dauerhafte Verbesserung von DobotDllType.py
Für das eigentliche Projekt kann es später sinnvoll sein, die DLL relativ zur Datei DobotDllType.py zu laden.
Statt:
return CDLL("DobotDll.dll", RTLD_GLOBAL)
könnte sinngemäß verwendet werden:
from pathlib import Path
dll_path = Path(__file__).resolve().parent / "DobotDll.dll"
return CDLL(str(dll_path), RTLD_GLOBAL)
Damit sucht das Modul die DLL immer in seinem eigenen Verzeichnis:
sdk64/
├── DobotDllType.py
└── DobotDll.dll
12. Fragen und Arbeitsaufträge für Schüler
- Was ist der Unterschied zwischen
Path.exists()und dem tatsächlichen Laden einer DLL? - Warum kann
DobotDllType.pyerfolgreich importiert werden, obwohlDobotDll.dllanschließend nicht geladen werden kann? - Welche Aufgabe hat
sys.path? - Was liefert
__file__? - Warum ist
dType.__file__für die Fehlersuche hilfreich? - Warum ist ein relativer Dateiname wie
"DobotDll.dll"weniger robust als ein vollständiger Pfad? - Welche Bedeutung hat die Unterscheidung zwischen 32-Bit- und 64-Bit-Software?
- Warum sollte eine Fehlersuche schrittweise aufgebaut sein?
Merksätze
- Importieren ist nicht dasselbe wie Laden einer nativen Bibliothek.
- Eine vorhandene Datei kann trotzdem nicht ladbar sein.
- Pfadprobleme sollten getrennt von Verbindungsproblemen untersucht werden.
- Gute Testprogramme geben sichtbar aus, welche Datei und welcher Pfad tatsächlich verwendet werden.
13. Empfohlene Reihenfolge für weitere Tests
os.add_dll_directory()testen.- Prüfen, ob
dType.load()erfolgreich ist. - Erst danach den Dobot über den aktuell vorhandenen COM-Port verbinden.
- Dann eine reine Leseoperation testen, zum Beispiel
GetPose(). - Erst anschließend Bewegungsbefehle testen.
14. Zusammenfassung in einem Satz
Der bisherige Test zeigt, dass DobotDllType.py korrekt importiert wird, die Datei DobotDll.dll vorhanden ist, aber die ursprüngliche load()-Funktion die DLL nur über ihren Dateinamen sucht; deshalb wird nun das Verzeichnis sdk64 mit os.add_dll_directory() ausdrücklich für die Windows-DLL-Suche registriert.