Denkfehler, Syntaxfehler oder ist ArcGIS schuld?

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
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

Hallo,

ich hab wieder mal ein Problem mit Python zusammen mit ArcGIS und hab inzwischen keine Ahnung wo der Fehler liegt. Ich probiere auch schon ganze 2 Tage lang rum, wo der Fehler liegt, kann es auch schon ein ganz klein wenig eingrenzen.

Ausgangssituation: ich habe eine Tabelle mit ganze vielen Attributen. Ein Attribut (KN) beinhaltet einen Schlüssel (gespeichert als Text), der eigentlich genau 8 Stellen haben müsste. Hat er aber nicht immer, daher will ich in einer neuen Spalte den Schlüssel korrigieren.

Da es sich hier wieder um Geodaten handelt, benutze ich wie immer ArcGIS, auch da vorher und hinterher noch mehr damit gemacht wird.

Es gibt nun ein ArcGIS Tool um die Werte zu Berechnen: http://webhelp.esri.com/arcgisdesktop/9 ... anagement)
(Hier mal der Link, damit ihr genauer nachvollziehne könnt, was das Tool macht und wie es benutzt werden sollte)

Dort gibt es auch tolle Codebeispiele und da steht z.B.

Code: Alles auswählen

expression = "getclass(float(!shape.area!))"
codeblock = "def getclass(area):\
        if area <= 1000:\
            return 1\
        if area > 1000 and area <= 10000:\
            return 2\
        else:\
            return 3"
gp.CalculateField_management(inputFC, "areaclass", expression, "PYTHON", codeblock)
Mein Code sieht so aus:

Code: Alles auswählen

grenzen = sys.argv[0]
expression = "getAGS(!KN!)"
codeblock = "def getAGS(KN):\
        if len(KN) == 12:\
          return KN.split(',')[0]\
        elif len(KN) == 3:\
          return '02000' + KN\
        elif len(KN) == 11:\
          return KN[0:5] + KN[8:11]\
        elif len(KN) >12:\
          return KN.split(',')[0]\
        elif len(KN) < 3:\
          return 'nichts'\
        else:\
          return KN"
gp.CalculateField_management(grenzen,"AGS2",expression,"PYTHON",codeblock)
Ist im Prinzip ja nix anderes. Trotzdem bekomme ich immer folgenden Fehler:

Code: Alles auswählen

Traceback (most recent call last):
  File "D:\Engel_DA\JOIN\test3.py", line 42, in -toplevel-
    gp.CalculateField_management(grenzen,"AGS2",expression,"PYTHON",codeblock)
RuntimeError: 
exceptions.SyntaxError: invalid syntax (line 1)
Failed to execute (CalculateField).[/quote]
...tbc...
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

Der Code ist imho falsch eingerückt. Versuchs mal so:

Code: Alles auswählen

grenzen = sys.argv[0] 
expression = "getAGS(!KN!)" 
codeblock = "def getAGS(KN):\ 
        if len(KN) == 12:\ 
            return KN.split(',')[0]\ 
        elif len(KN) == 3:\ 
            return '02000' + KN\ 
        elif len(KN) == 11:\ 
            return KN[0:5] + KN[8:11]\ 
        elif len(KN) >12:\ 
            return KN.split(',')[0]\ 
        elif len(KN) < 3:\ 
            return 'nichts'\ 
        else:\ 
            return KN" 
gp.CalculateField_management(grenzen,"AGS2",expression,"PYTHON",codeblock)
oder so:

Code: Alles auswählen

grenzen = sys.argv[0] 
expression = "getAGS(!KN!)" 
codeblock = "def getAGS(KN):\ 
        if len(KN) == 12:\ 
                return KN.split(',')[0]\ 
        elif len(KN) == 3:\ 
                return '02000' + KN\ 
        elif len(KN) == 11:\ 
                return KN[0:5] + KN[8:11]\ 
        elif len(KN) >12:\ 
                return KN.split(',')[0]\ 
        elif len(KN) < 3:\ 
                return 'nichts'\ 
        else:\ 
                return KN" 
gp.CalculateField_management(grenzen,"AGS2",expression,"PYTHON",codeblock)
Allgemein ist dieses CalculateField recht tückisch, die Fehler sind nie besonders detailliert.
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

...

Da ich dass Problem nicht so richtig nachvollziehen konnte, hab ich einfach folgendes Probiert:
im ArcGIS das Toolboxfenster geöffnet und einfach mal per HAnd probiert ob mein Code funktioniert:

http://www.mariaengel.de/wp-content/upl ... oolbox.jpg

so eingegeben, praktisch auch nichts anderes, als im Scrip, funktioniert das ganze problemlos.


Darauf hin, hab ich im Script meinen codeblock auseinander genommen und rumprobiert.
Wenn da z.B nur steht

Code: Alles auswählen

codeblock = "def getAGS(KN):\
 return KN.split(',')[0]"

gibt es auch keine Fehlermeldung und ich krieg richtig nur den Teil vorm "," ausgegeben.

Sobald da ein if dazu kommt und wenn es nur eins ist, bekomme ich den beeits genannten Fehler.

Hab ich nun irgendwo einen Denkfehler und seh irgendwas nicht? Gibt es irgend einen Trick, den ich nicht kenne, oder ist das ganze eher nen ArcGIS Problem.

Alternativ könnte ich mir eine 2. Spalte erstellen, in der ich die Länge von KN ausgeben lasse, dann vorher Selectiere und immer nur ganz Bestimmte Fälle berechne. Will ich aber nicht wirklich, weil es muss doch auch so funktionieren. *ein wenig frustriert bin*
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

BlackVivi hat geschrieben:Der Code ist imho falsch eingerückt. Versuchs mal so:
...
Allgemein ist dieses CalculateField recht tückisch, die Fehler sind nie besonders detailliert.
Hatte eigentlich drauf geachtet, dass die Einrückungen richtig sind und dann zum Probieren zwischen dem Toolboxfenster und meinem Script hin und her kopiert, da muss beim rauskopieren aus der Toolbox, was verrückt sein.

Hab jetzt beide deiner Beispiele probiert, bringt leider nix, weiterhin der gleiche Fehler.
BlackJack

Das Codebeispiel kann nicht funktionieren. Gib doch einfach mal `codeblock` auf der Konsole aus:

Code: Alles auswählen

def main():
    codeblock = "def getAGS(KN):\
        if len(KN) == 12:\
          return KN.split(',')[0]\
        elif len(KN) == 3:\
          return '02000' + KN\
        elif len(KN) == 11:\
          return KN[0:5] + KN[8:11]\
        elif len(KN) >12:\
          return KN.split(',')[0]\
        elif len(KN) < 3:\
          return 'nichts'\
        else:\
          return KN"

    print codeblock
Da kommt folgendes heraus (Umbruch hat mein Terminal gemacht, wäre sonst *eine Zeile*):

Code: Alles auswählen

def getAGS(KN):        if len(KN) == 12:          return KN.split(',')[0]        elif len(KN) == 3:          return '02000' + KN        elif len(KN) == 11:          return KN[0:5] + KN[8:11]        elif len(KN) >12:          return KN.split(',')[0]        elif len(KN) < 3:          return 'nichts'        else:          return KN
Dass das kein gültiges Python ist, sollte klar sein. Bei der Zeilenfortsetzung mit '\' wird die folgende Zeile einfach angehängt *ohne* einen Zeilenwechsel dazwischen. Das ist ja gerade der Sinn vom '\'. Wenn man einen Zeilenwechsel machen dürfte, bräuchte man die Zeilenfortsetzung ja nicht.

Entweder Du schreibst mühselig ans Ende jeder Zeile '\n\', also ein Zeilenende vor der Zeilenfortsetzung, oder Du benutzt mehrzeilige Zeichenketten:

Code: Alles auswählen

codeblock = '''\
def spam(eggs):
    if eggs is None:
        pass
'''
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

Hallo BlackJack,

Danke vielmals. Jetzt geht es natürlich ... *aufatme

:oops:

*Kopf gegen die Wand schlag* ... zu dumm ...

Aber dann müssten die Beispiele aus der Hilfe vom ArcGIS auch nicht funktionieren, denn dort steht es ja haargenauso falsch drin, wie ich es hatte. Oder hab ich was übersehen?

Die 2. Variante mit den mehrzeilige Zeichenketten gefällt mir dann aber doch besser, als das mühseelige \n\ am Ende jeder Zeile.

Danke.
Antworten