Problem mit gtk und xml.etree.ElementTree

Programmierung für GNOME und GTK+, GUI-Erstellung mit Glade.
Antworten
JanW1989
User
Beiträge: 4
Registriert: Donnerstag 20. Juni 2013, 10:51

Hallo,

ich habe erst kürzlich mit Python begonnen und stehe vor einem Problem, dass ich nicht lösen kann.
Ich hole mit xml.etree.ElementTree einige Daten aus einer xml-Datei heraus, die ich gerne in einer gtk Gui weiterverwenden möchte.
Die xml-Operationen klappen auch wunderbar, aber sobald ich das gtk Paket importiere (import gtk) und selbst wenn ich damit nichts anstelle funktioniert das Skript (das vorher wunderbar gelaufen ist) nicht mehr. Ich verwende Python 2.6.6

Hier mein Code:

Code: Alles auswählen

#!/usr/bin/python

import xml.etree.ElementTree
import gtk

class Section:

   def __init__(self, airfoil_file, SectionNo):

      #Attributes

      self.MomInertMin = 0
      self.MomInertMax = 0
      self.Area = 0
      self.ThroatRatio = 0
      self.ThicknessRatio = 0
      self.ThicknessMax = 0
      self.GridWidth = 0
      self.ChordLength = 0
      self.PositionCGTheta = 0
      self.PositionCGAxial = 0
      self.PositionTETheta = 0
      self.PositionTEAxial = 0
      self.PositionLETheta = 0
      self.PositionLEAxial = 0

      baum = xml.etree.ElementTree.parse(airfoil_file)

      sections = baum.findall("Blades/Blade/Sections/Section")
      for i in sections:
         if i.get("Name") == ("Section 0" + str(SectionNo)):
            section = i

      parameters = section.findall("DerivedValues/Parameter")

      for i in parameters:
         if i.get("name") == "MomIntert Min":
            self.MomInertMin = i.get("value")

      for i in parameters:
         if i.get("name") == "MomIntert Max":
            self.MomInertMax = i.get("value")

      for i in parameters:
         if i.get("name") == "Area":
            self.Area = i.get("value")

      for i in parameters:
         if i.get("name") == "ThroatRatio":
            self.ThroatRatio = i.get("value")

      for i in parameters:
         if i.get("name") == "ThicknessRatio":
            self.ThicknessRatio = i.get("value")

      for i in parameters:
         if i.get("name") == "ThickessMax":
            self.ThicknessMax = i.get("value")

      for i in parameters:
         if i.get("name") == "GridWidth":
            self.GridWidth = i.get("value")

      for i in parameters:
         if i.get("name") == "ChordLength":
            self.ChordLength = i.get("value")

      for i in parameters:
         if i.get("name") == "Position CG Theta":
            self.PositionCGTheta = i.get("value")

      for i in parameters:
         if i.get("name") == "Position CG Axial":
            self.PositionCGAxial = i.get("value")

      for i in parameters:
         if i.get("name") == "Position TE Theta":
            self.PositionTETheta = i.get("value")

      for i in parameters:
         if i.get("name") == "Position TE Axial":
            self.PositionTEAxial = i.get("value")

      for i in parameters:
         if i.get("name") == "Position LE Theta":
            self.PositionLETheta = i.get("value")

      for i in parameters:
         if i.get("name") == "Position LE Axial":
            self.PositionLEAxial = i.get("value")

sec1 = Section("airfoil.xml", 1)
print sec1.Area
Und die Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "Section.py", line 92, in <module>
    sec1 = Section("airfoil.xml", 1)
  File "Section.py", line 27, in __init__
    baum = xml.etree.ElementTree.parse(airfoil_file)
  File "/usr/lib64/python2.6/xml/etree/ElementTree.py", line 862, in parse
    tree.parse(source, parser)
  File "/usr/lib64/python2.6/xml/etree/ElementTree.py", line 581, in parse
    parser = XMLTreeBuilder()
  File "/usr/lib64/python2.6/xml/etree/ElementTree.py", line 1118, in __init__
    "No module named expat; use SimpleXMLTreeBuilder instead"
ImportError: No module named expat; use SimpleXMLTreeBuilder instead
Ist jemand schon mal auf ein ähnliches Problem gestoßen und kann mir helfen? Vielen Dank und viele Grüße!
Jan
Zuletzt geändert von Anonymous am Donnerstag 20. Juni 2013, 11:12, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

@JanW1989: Was passiert bei einem ``import xml.parsers.expat`` als letztem Import mit und ohne das ``import gtk``?

Hat sich ausser der Import-Zeile wirklich nichts geändert am Quelltext oder an der Art und Weise wie das Programm ausgeführt wird?

Sonstige Anmerkungen: Der Quelltext weicht vom Style Guide for Python Code ab. Insbesondere bei der Einrücktiefe sollte man das nicht tun.

Man sollte immer von `object` Erben wenn es sonst keine Basisklasse gibt, weil sonst nicht alle Spracheigenschaften mit nutzbar sind, wie beispielsweise `property()`.

Der Name `airfoil_file` ist irreführend weil es kein Dateiobjekt ist, sondern ein Datei*name*.

Kommentare sollten zusätzliche Informationen liefern. Vor der offensichtlichen Definition von Attributen muss man nicht noch mal kommentieren, dass dort Attribute stehen.

Wenn mehrere Attribute einen gemeinsamen Namenspräfix haben, kann das ein Zeichen sein, dass sie zusammen einen eigenen Datentyp bilden.

`i` sollte man, insbesondere in einer Schleife, nur an ganze Zahlen binden und nicht an beliebige Objekte. Sonst bricht man mit den Erwartungen sehr vieler Programmierer.

Fangen tatsächlich alle Nummern bei den 'Name'-Attributen in <Section>-Elementen mit einer 0 an oder haben die eine feste Stellenanzahl die mit 0en aufgefüllt werden?

Der Code berücksichtigt nicht den Fall, dass die gewünschte Section nicht gefunden wird.

Statt immer wieder die Schleife zu kopieren, die über die linear über die Parameter iteriert, nur um dann einen davon rauszupicken, sollte man einmal über alle iterieren und dabei ein Wörterbuch aufbauen.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python
from xml.etree import ElementTree as etree


class Section(object):

    def __init__(self, airfoil_filename, section_number):
        tree = etree.parse(airfoil_filename)
        for section in tree.findall('Blades/Blade/Sections/Section'):
            if section.get('Name') == 'Section 0{0}'.format(section_number):
                break
        else:
            raise ValueError('section {0} not found'.format(section_number))
        
        parameters = dict(
            (n.get('name'), n.get('value'))  # TODO: Hier eventuell ein `float()` auf den Wert anwenden?
            for n in section.findall('DerivedValues/Parameter')
        )
        self.mom_inert_min = parameters['MomIntert Min']
        self.mom_inert_max = parameters['MomIntert Max']
        self.area = parameters['Area']
        self.throat_ratio = parameters['ThroatRatio']
        self.thickness_ratio = parameters['ThicknessRatio']
        self.thickness_max = parameters['ThicknessMax']
        self.grid_width = parameters['GridWidth']
        self.chord_length = parameters['ChordLength']
        self.position_cg_theta = parameters['Position CG Theta']
        self.position_cg_axial = parameters['Position CG Axial']
        self.position_te_theta = parameters['Position TE Theta']
        self.position_te_axial = parameters['Position TE Axial']
        self.position_le_theta = parameters['Position LE Theta']
        self.position_le_axial = parameters['Position LE Axial']


def main():
    section = Section('airfoil.xml', 1)
    print section.area


if __name__ == '__main__':
    main()
JanW1989
User
Beiträge: 4
Registriert: Donnerstag 20. Juni 2013, 10:51

Okay, ich habe das Programm jetzt zum Laufen gebracht.

Code: Alles auswählen

from lxml import etree
Parsen konnte ich dann mit

Code: Alles auswählen

baum = etree.parse("airfoil.xml")
Trotzdem frage ich mich, welches Problem es mit dem xml Modul gibt?!

Geändert:
Vielen Dank! Wir haben unseren Beitrag anscheinend fast gleichzeitig verfasst. An deine Vorschläge werde ich mich halten. Die sind für den Anfang sicherlich gold wert und helfen mir bei meinem "learning-by-doing"-Vorgehen! Ich werde versuchen deine Hinweise einzubauen und dann meld ich mich nochmal.

Viele Grüße
JanW1989
User
Beiträge: 4
Registriert: Donnerstag 20. Juni 2013, 10:51

Wenn ich

Code: Alles auswählen

import xml.parsers.expat
hinzufüge bekomme ich einen ImportError:

Code: Alles auswählen

Traceback (most recent call last):
  File "Section.py", line 11, in <module>
    import xml.parsers.expat
  File "/usr/lib64/python2.6/site-packages/_xmlplus/parsers/expat.py", line 4, in <module>
    from pyexpat import *
ImportError: /usr/lib64/python2.6/site-packages/_xmlplus/parsers/pyexpat.so: symbol XML_SetHashSalt, version EXPAT_2_0_1_RH not defined in file libexpat.so.1 with link time reference
Deine restlichen Vorschläge habe ich eingearbeitet und alles klappt wunderbar.
Eine Frage habe ich aber noch zu dem Dictionary. So wie du es programmiert hast, funktioniert es bei mir nicht. Er makelt die for-Schleife an.

Meine Lösung ist folgende, aber da es ja, wenn ich es richtig verstanden habe, mehrere varianten gibt, wäre ich für eine Erklärung sehr dankbar!

Code: Alles auswählen

parameters = {}
    for n in section.findall('DerivedValues/Parameter'):
        parameters[n.get('name')] = n.get('value')
Viele Grüße,
Jan
BlackJack

@JanW1989: Dann passt die expat-Bibliothek nicht zum Python-Modul. AFAIK gab es mal ein Python-Sicherheitsupdate bezüglich der `hash()`-Funktion und Debian hat da beim paketieren Mist gebaut.

Was ist denn bei meinem Generatorausdruck das Problem?
JanW1989
User
Beiträge: 4
Registriert: Donnerstag 20. Juni 2013, 10:51

Entschuldigung, dein Code funktioniert doch. Anscheinend lag mein Fehler vorher an einer anderen Stelle.
An dem Python-Modul kann ich leider nicht viel ändern, da ich auf einem Cluster arbeite.
Vielen Dank für deine Antworten!
Antworten