Ich hatte letzte Woche eine Frage zum Anpassen einer ToolValidator-Klasse gestellt und einige sehr gute Antworten erhalten. Bei der Arbeit mit den vorgeschlagenen Lösungen habe ich ein benutzerdefiniertes Modul erstellt, das Abfragen für eine Datenbank ausführt und sowohl von der ToolValidator-Klasse (um Werte für die Dropdown-Listen bereitzustellen) als auch später im Geoverarbeitungsskript (um andere zu erhalten) aufgerufen wird Parameter basierend auf Elementen, die in Dropdown-Listen ausgewählt wurden). Ich kann das benutzerdefinierte Modul in der ToolValidator-Klasse jedoch nicht aufrufen. Ich habe versucht, ohne Glück an den Pfad anzuhängen. Wenn ich versuche, diese Änderungen auf das Skript anzuwenden, wird ein Laufzeitfehler angezeigt: [Errno 9] Ungültiger Dateideskriptor. Wenn ich die Importzeile auskommentiere, keine Fehler.
sys.path.append('my_custom_module_directory')
import my_custom_module
Viele von Ihnen fragen sich vielleicht, warum ich nicht einfach ein benutzerdefiniertes Tool mit ArcObjects implementiere. Der Grund dafür ist, dass meine Endbenutzer nicht über die erforderlichen Berechtigungen verfügen, um DLLs auf ihrem Computer zu registrieren.
UPDATE: Dies ist mir in ArcGIS 10 passiert. Interessanterweise habe ich zunächst den Pfad innerhalb der Funktion initialiazeParameters der ToolValidator-Klasse angehängt. Wenn ich das Anhängen außerhalb (dh über) der ToolValidator-Klasse durchführe, funktioniert alles wie erwartet.
sys.path.append('C:/Working/SomeFolder')
import somescript -------->THIS WORKS
class ToolValidator:
"""Class for validating a tool's parameter values and controlling
the behavior of the tool's dialog."""
def __init__(self):
"""Setup arcpy and the list of tool parameters."""
import arcpy
sys.path.append('C:/Working/SomeFolder')
import somescript -------> THIS DOESNT WORK
self.params = arcpy.GetParameterInfo()
UPDATE 2: Ich glaube, ich habe die wahre Ursache meines Problems gefunden. In den Codefragmenten in diesem Beitrag habe ich scheinbar echte Pfade (z. B. C: / Working / SomeFolder) an den sys.path angehängt. In meiner eigentlichen ToolValidator-Klasse habe ich einen relativen Pfad mit os.path.dirname(__file__)
+ "\ my_special_folder ..." erstellt. Ich hatte erwartet, dass os.path.dirname(__file__)
dies den Pfad der Toolbox zurückgeben würde, da dieser die ToolValidator-Klasse enthält. Ich habe festgestellt, dass dies nicht der Fall ist. Soweit ich das beurteilen kann, wird die ToolValidator-Klasse niemals in eine .py-Datei geschrieben, und ich spekuliere, dass dieser Code an den Python-Interpreter im Speicher übergeben wird, also __file__
nutzlos ist oder ein temporäres Skript beibehalten und dann ausgeführt wird ( path_to_script) wird aufgerufen und erneut gerendert__file__
nutzlos. Ich bin sicher, es gibt noch andere Gründe, die mir fehlen.
Kurz gesagt, wenn ich einen fest codierten Pfad verwende, funktioniert sys.append überall, relative Pfade funktionieren in der ToolValidator-Klasse nicht so gut.
quelle
Antworten:
So starte ich nach dem Starten von ArcGIS oder ArcCatalog zunächst ein Dummy-Tool ("Einmal ausführen"), das ein Dummy.py-Skript aufruft. Danach können Sie Python-Skripte mit sys.argv [0] in den Validator importieren. Dies zeigt auf den Ordner, in dem sich das erste Skript befand. Danach können Sie das benötigte Skript in die Validator-Klasse importieren.
Das Dummy.py-Skript, das vom Tool "Einmal ausführen" aufgerufen wird:
Entschuldigung, ich kann die Formatierung nicht richtig einstellen. Grüße, Maarten Tromp
quelle
Endlich diesen schrecklichen Käfer geknackt! Wenn Sie beispielsweise versuchen, Änderungen zum Importieren eines relativen Moduls oder Pakets anzuwenden, wird möglicherweise der folgende Fehler angezeigt:
Option 1: Fügen Sie
nur für Entwickler den vollständigen Pfad zum Modul zum PYTHONPATH hinzu . Sie müssen ArcMap / ArcCatalog neu starten, bevor es wirksam wird. Verwenden Sie den folgenden Code, um das Modul aus einem relativen Pfad zu importieren (für die Bereitstellung). Keine Sorge, der Endbenutzer benötigt keine Ergänzungen zu seiner PYTHONPATH-Variablen, es wird funktionieren!
Option 2:
Fügen Sie dem folgenden Code eine zusätzliche Zeile hinzu, um den fest codierten Pfad anzuhängen, z. B.: Sys.path.append (r "c: \ temp \ test \ scripts")
Wenn Sie zur Bereitstellung bereit sind, haben Sie eine Fremdverzeichnis, aber es spielt keine Rolle, alles sollte auf dem Computer des Endbenutzers funktionieren, da der erste Pfad, den Sie hinzugefügt haben, das relative Verzeichnis war (unser Ziel war es, nur den Fehlerdialog zu überwinden).
Code, der beiden Optionen gemeinsam ist:
Aktualisieren
Leb wohl, böses Ausschneiden und Einfügen! Ich habe das Codebeispiel aktualisiert, damit die ToolValidator-Klasse aus der Bibliothek importiert wird. Ich schneide und füge nur einmal ein, wenn die Werkzeugparameter zum ersten Mal eingestellt werden. Ich speichere diesen Code-Snippit in der Dokumentzeichenfolge des zu importierenden ToolValidator.
In diesem Beispiel basiert der Name des Quellverzeichnisses auf dem TBX-Namen. Dieser Ansatz vermeidet Kollisionen, wenn Sie zwei Toolboxen mit unterschiedlichen Quellverzeichnissen haben. Der Standard, den ich für die Benennung von
Quellordnern verwendet habe, lautet wie folgt: TOOLBOXNAME__anything.tbx -> TOOLBOXNAME.src
Warum das "__anything"? Da Binärdateien in unserem DVCS nicht zusammengeführt werden können, können wir Einzelpersonen Tools zuweisen, ohne Änderungen zu verlieren. Wenn das Werkzeug fertiggestellt ist, wird es ausgeschnitten und in den Master eingefügt.
Ich musste auch auf Dateien im Quellordner zugreifen, um ein Dropdown-Menü zu füllen. Verwenden Sie diese Methode , um den Pfad zur Toolbox aus Ihrem importierten Modul abzurufen :
quelle
Das Einfügen der Importe an die Spitze des Validierungsmoduls außerhalb der
ToolValidator
Klasse scheint für mich in Ordnung zu sein - ich bin auf 10.0 SP2. Ich mache jedoch nichts anderes mit dem importierten Modul als inupdateParameters
.quelle
Ich konnte meine Validierung in eine py-Datei verschieben, indem ich sie importierte und aus der vorhandenen TBX-Toolvalidierung heraus aufrief. Der Schlüssel rief den Import im Konstruktor auf. Wenn ich es von außerhalb der ToolValidator-Klasse aufgerufen habe, ist der Import fehlgeschlagen. Hier ist, was ich auf der Registerkarte Validierung der TBX hatte.
Meine Validierungslogik lebte dann in ExportParcelIntersected.ToolValidator (). Wo es einfacher gewartet werden könnte.
quelle