Rückgabe abhängig vom Aufrufer

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
sfx2k
User
Beiträge: 54
Registriert: Dienstag 2. September 2014, 13:29

Hallo zusammen,

mein Ziel ist es, die Ausgabe des Scriptes je nach Aufrufer unterschiedlich zu halten.
Wird das Script direkt von der Console aus gestartet, soll die Ausgabe als String in die Console erfolgen.
Erfolgt der Aufruf allerdings aus einem anderen Script, so möchte ich eine Liste ausgeben, um diese dann ggf. weiter zu verarbeiten.

Ich habe das jetzt folgendermaßen gelöst, und frage mich, ob das auch schöner geht, und was sonst noch zu verbessern wäre.

Über Eure Kommentare freue ich mich.

Code: Alles auswählen


def ocr_tags_values(filename):

    with open(filename, 'rU') as fileobject:
        ocr_data = fileobject.read()
    tagnames = ['feldwert', 'fieldvalue']
    liste = []
    matches = re.findall(r'''
                        <(.*)>.*                       # Tag
                        \n                             # Umbruch
                        .*<(?:{0})>(.*)</(?:{0})>      # Wert
                        '''
                         .format('|'.join(tagnames)),
                         ocr_data,
                         re.VERBOSE + re.IGNORECASE)
    for match in matches:
        liste.append(match[0] + ': ' + match[1])

    # Wenn Aufruf von außen, dann Strings zurückgeben
    if __name__ == '__main__':
        for item in liste:
            print item
    # sonst die Liste
    else:
        return liste

# *****************************************************************************

# Für externen Aufruf, bspw. von der Console
if __name__ == '__main__':
    if len(sys.argv) <= 1:
        print u'Bitte Dateinamen übergeben'
    else:
        ocr_tags_values(sys.argv[1])
        
      
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@sfx2k: eine Funktion sollte sich immer gleich halten. Die Ausgabe erfolgt damit im Hauptprogramm:

Code: Alles auswählen

if __name__ == '__main__':
    for item  in ocr_tags_values(sys.argv[1]):
        print item
XML-Dateien darfst Du NIE per regulärem Ausdruck auslesen. XML ist keine Text-Datei. Dafür gibt es entsprechende Bibliotheken, wie z.B. ElementTree.
sfx2k
User
Beiträge: 54
Registriert: Dienstag 2. September 2014, 13:29

Hallo Sirius3,

danke für Deine Antwort.

Ich werde dann mal versuchen, das Ganze auf XML-Verarbeitung umzustellen.

Verrätst Du mir noch, warum ich das mit RegExp nicht darf? Aus Performance-Gründen? Weil es eine explizit dafür gedachte Lösung (ElementTree) gibt?
Denn prinzipiell ist auch eine XML-Datei ja eine Text-Datei ;)
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

sfx2k hat geschrieben:Verrätst Du mir noch, warum ich das mit RegExp nicht darf? Aus Performance-Gründen? Weil es eine explizit dafür gedachte Lösung (ElementTree) gibt?
Weil du damit Cthulhu heraufbeschwörst: https://stackoverflow.com/questions/173 ... 54#1732454
sfx2k hat geschrieben:Denn prinzipiell ist auch eine XML-Datei ja eine Text-Datei ;)
In diesem Sinn sind auch die meisten Programmiersprachen-Dateien bloß Text. Du bist aber nicht an den textuellen Eigenschaften von XML-Dateien interessiert, also in welcher Codierung (utf-8, cp1252, ...) sie vorliegen oder welche Art von Zeilenumbrüchen sie haben (DOS, Unix), sondern an ihren grammatischen Eigenschaften. Und Grammatiken kommen in verschiedenen Graden daher in Bezug darauf, welche Art von Parser man benötigt, um Texte in diesen Grammatiken zu parsen (https://de.wikipedia.org/wiki/Chomsky-Hierarchie). Reguläre Ausdrücke - der Name deutet es an - kann man nur benutzen, um reguläre Sprachen zu parsen. Kontextfreie Sprachen wie XML kann man damit nicht parsen, dazu benötigt man Rekursion oder einen Keller-Automaten, AKA Stack. Um das zu verstehen versuch mal, einen regulären Ausdruck zu schreiben, der alle und ausschließlich Strings parst, die aus einer beliebigen Anzahl von a gefolgt von exakt derselben Anzahl von b bestehen, zB. "", "ab", "aaaaaaaaaaabbbbbbbbbbb". Zusatzpunkte gibt es, wenn du erkennst, was das mit XML zu tun hat.

Außerdem ist Faulheit beim Programmierer eine Tugend. Wenn es ein fertiges Werkzeug gibt, das tut, was du benötigst, dann verwende das, statt selber etwas zu basteln.
In specifications, Murphy's Law supersedes Ohm's.
sfx2k
User
Beiträge: 54
Registriert: Dienstag 2. September 2014, 13:29

pillmuncher hat geschrieben:
sfx2k hat geschrieben:Verrätst Du mir noch, warum ich das mit RegExp nicht darf? Aus Performance-Gründen? Weil es eine explizit dafür gedachte Lösung (ElementTree) gibt?
Weil du damit Cthulhu heraufbeschwörst: https://stackoverflow.com/questions/173 ... 54#1732454
Ups, das möchte ich wirklich nicht :cry:
Danke für Deine Ausführungen :)

Ich habe das Ganze jetzt mal auf lxml umgebaut.
Was meint Ihr; was kann man noch mehr pythonic machen?

Code: Alles auswählen

from lxml import etree as et
import sys

# *****************************************************************************

def ocr_tags_values(filename):

    '''
    Stellt Tags und FieldValues in OCR-Dateien übersichtlich dar.

    In: Filename (string)
    Out: List
    '''

    tree = et.parse(filename)
    root = tree.getroot()
    
    liste = []
    for feldwert in root.findall('.//feldWert'):
        parent = feldwert.getparent()
        if parent.tag == 'ja':
            parent_text = parent.getparent().tag + '_ja' 
        elif parent.tag == 'nein':
            parent_text = parent.getparent().tag + '_nein' 
        else:
            parent_text = parent.tag
        liste.append(parent_text + ': ' + feldwert.text)

    return liste

# *****************************************************************************

if __name__ == '__main__':
    if len(sys.argv) <= 1:
        print u'Bitte Dateinamen übergeben'
    else:
        for item in ocr_tags_values(sys.argv[1]):
            print item
Zuletzt geändert von Anonymous am Montag 27. Juni 2016, 21:26, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@sfx2k: Die Ausgabe formatiert man üblicherweise dann, wenn man auch wirklich was ausgibt. Will man die Tags und Values in einer anderen Form haben, muß man bei Deinem Ansatz eine neue Funktion schreiben. Ansonsten ist die Funktion ja kurz und hat eine klare Aufgabe, also wenig Optimierpotential (außer dem unnötigen Lattenzaun):

Code: Alles auswählen

import sys
from lxml import etree as et

def extract_ocr_tags_values(filename):
    '''
     Extrahiert Tags und FieldValues aus einer OCR-Dateien.
 
     In: Filename (string)
     Out: List
     '''
    tree = et.parse(filename)
    root = tree.getroot()
   
    result = []
    for feldwert in root.findall('.//feldWert'):
        parent = feldwert.getparent()
        if parent.tag in ('ja', 'nein'):
            parent_text = '{}_{}'.format(parent.getparent().tag, parent.tag)
        else:
            parent_text = parent.tag
        result.append((parent_text, feldwert.text))
    return result
 
if __name__ == '__main__':
    if len(sys.argv) <= 1:
        print u'Bitte Dateinamen übergeben'
    else:
        for tag, value in extract_ocr_tags_values(sys.argv[1]):
            print '{}: {}'.format(tag, value)
sfx2k
User
Beiträge: 54
Registriert: Dienstag 2. September 2014, 13:29

Super, vielen Dank.
Doch noch etwas optimiert :)

Die Lattenzaunzeilen füge ich halt immer wegen der Übersichtlichkeit hinzu.
Aber wenn das nicht pythonic ist, lasse ich sie weg ;)
Antworten