2017-02-01 6 views
3

Ich versuche, eine Textdatei zu durchlaufen und einige Logik anwenden, aber ich bin nicht in der Lage, die Textdatei zu durchlaufen. Also zur Zeit habe ich eine Textdatei, die wie folgt strukturiert:Fehler beim Durchlaufen einer Textdatei in Python

--- section1 --- 
"a","b","c" 
"d","e","f" 
--- section2 --- 
"1","2","3" 
"4","5","6" 
--- section3 --- 
"12","12","12" 
"11","11","11" 

Ich versuche, die erste Zeile, um herauszufiltern, die enthält ‚---‘ und wandeln die Linien unten in json bis zum nächsten ‚--- 'Zeile erscheint im Textdokument.

aber ich habe diesen Fehler "Felder1 = next (Datei) .split ('') StopIteration

with open(fileName,'r') as file: 
    for line in file: 
     if line.startswith('-') and 'section1' in line: 
      while '---' not in next(file): 
       fields1 = next(file).split(',') 
       for x in range(0,len(fields1)): 
        testarr.append({ 
        config.get('test','test'): fields1[x]   
        }) 

       with open(test_dir,'w') as test_file: 
        json.dump(testarr, test_file) 

Jede Idee, warum mein Code nicht funktioniert oder wie kann ich den Fehler beheben kann?

+1

Versuchen Sie, zwei Schleifen in Reihe zu schreiben, anstatt sie zu verschachteln. Loop1: Überspringe alle Zeilen bis '--- section1 ...'. Loop2: Dump alle Zeilen, bis ein anderes '---' erfüllt ist. –

+0

Angesichts früherer Erfahrungen mit ähnlichen Titeln habe ich erwartet, dass dies eine Mistfrage ist, die geschlossen werden muss. Stattdessen fand eine gut formulierte, klare Frage mit praktisch allen relevanten Informationen. Viele Kudos OP. –

+0

Ignoriere meinen ursprünglichen (jetzt gelöschten) Kommentar. Es ist lange her, seit ich eine 'else'- zu einer' while'-Schleife gesehen habe. –

Antwort

2

Sieht aus wie Sie Fragen massiv sind overcomplicating die next innerhalb der inneren while Schleife ich stelle mir vor, um die äußere for Schleife Stolpern, aber das ist nur sowieso unnötig Du über die Leitungen bereits Looping;.. die, die holen Sie wollen, dann beenden, wenn du bist don e.

with open(fileName,'r') as inputfile: 
    for line in inputfile: 
     if line.startswith('-') and 'section1' in line: 
      continue 
     elif line.startswith('-'): 
      break 
     else: 
      testarr.append({config.get('test', 'test'): x 
       for x in line.split(',')}) 

with open(test_dir,'w') as test_file: 
    json.dump(testarr, test_file) 

Ich hoffe, ich habe das append Recht, wie ich auch Sie wollte zeigen, wie die Split-Felder mehr elegant abzubilden, aber ich bin nicht sicher, ob ich völlig verstehen, was Ihr ursprünglicher Code tat. (Ich vermute, Sie werden die \n vom Ende der Linie trimmen wollen, bevor sie spalten, eigentlich. Auch ich denke, Sie wollen die Zitate trimmen aus um jeden Wert. x.strip('"') for x in line.rstrip('\n').split(','))

I umbenannt auch file zu inputfile, um zu vermeiden, mit dem reservierten Schlüsselwort file zu kollidieren.

Wenn Sie mehr Dateien schreiben möchten, fügen Sie im Grunde mehr Zustände in die Schleife ein und verschieben Sie das Schreib-Snippet zurück in die Schleife. Ich möchte nicht unbedingt erklären, wie dies einer Zustandsmaschine entspricht, aber es sollte nicht schwer zu verstehen sein: Mit zwei Zuständen überspringen oder sammeln Sie; Um dies zu erweitern, fügen Sie einen weiteren Status für die Begrenzung hinzu, wenn Sie zurückfalten, wo Sie die gesammelten Daten ausschreiben und die gesammelten Zeilen auf keine initialisieren.

+0

Die äußere "for" -Schleife ist nicht das, was das Problem verursacht. Dies wird in der Frage klar dargelegt. –

+0

Außerdem fügt Ihr Code alle Zeilen hinzu, die nicht in Abschnitt1 enthalten sind. –

+0

Huh? Der 'elif' springt zum Ende, wenn Sie Abschnitt 2 erreichen. – tripleee

0

next() löst eine StopIteration Ausnahme aus, wenn der Iterator erschöpft ist. Mit anderen Worten, Ihr Code wird an das Ende der Datei geleitet, und Sie rufen erneut next() auf, und es gibt nichts mehr, was zurückgegeben werden kann. Daher wird diese Ausnahme ausgelöst.

Was, wie Ihr Problem zu lösen, ich denke, das könnte sein, was Sie wollen:

with open(fileName, 'r') as file: 
    for line in file: 
     if line.startswith('---'): 
      if 'section1' in line: 
       continue 
      else: 
       break 
     fields1 = line.split(',') 
     for x in range(len(fields1)): 
      testarr.append({ 
       config.get('test', 'test'): fields1[x] 
      }) 

with open(test_dir, 'w') as test_file: 
    json.dump(testarr, test_file) 
+0

Angesichts der Eingabedatei erklären Sie nicht wirklich, wie es möglich ist, das Ende der Datei zu erreichen, wenn die Stoppbedingung eine Zeile ist, die '---' enthält. –

+0

Auch dieser Schreibvorgang muss außerhalb der Schleife liegen. –

+0

@MadPhysicist So tut es. Vielen Dank. – Dan

2

Die Ursache des Fehlers ist, dass Sie das Dateiobjekt genrator missbräuchlich durch next fordert sie auf, doppelt so häufig wie Sie denken. Jeder Anruf an next erhält eine Zeile und gibt sie zurück. Daher erhält while '---' not in next(file): fields1 = next(file).split(',') eine Zeile, überprüft es für ---, ruft dann eine andere Zeile und versucht, es zu analysieren. Dies bedeutet, dass Sie eine Zeile mit der --- überspringen können, indem Sie sie in der zweiten next erscheinen lassen. In diesem Fall gelangen Sie an das Ende der Datei, bevor Sie die Zeile gefunden haben, nach der Sie suchen. StopIteration ist, wie Iteratoren normalerweise angeben, dass ihre Eingabe erschöpft ist.

Es gibt ein paar anderen Dinge, die Sie in Ihrem Code ansprechen möchten:

  1. Mit next auf einem Generator wie eine Datei, wenn Sie sind bereits in einer for Schleife undefiniertes Verhalten führen kann. Sie kommen dieses Mal vielleicht davon, aber es ist im Allgemeinen keine gute Übung. Der Hauptgrund, warum Sie damit wegkommen, ist übrigens, dass Sie nie tatsächlich die Kontrolle an die for Schleife zurückgeben, sobald die while ausgelöst wird, und nicht, dass Dateien in dieser Hinsicht besonders freizügig sind.
  2. Die innere with, die Ihre Daten in eine Datei ablegt, befindet sich in Ihrer while Schleife. Das bedeutet, dass die Datei, die Sie mit 'w' Berechtigungen öffnen, für jede Iteration des while (d. H. Jede Zeile in der Datei) abgeschnitten wird. Wenn das Array wächst, wird die Ausgabe tatsächlich gut aussehen, aber Sie möchten das wahrscheinlich aus der inneren Schleife verschieben.

Die einfachste Lösung wäre, den Code in zwei Schleifen neu zu schreiben: man den Anfang des Teils Sie interessieren zu finden, und die andere, sie zu verarbeiten, bis zum Ende zu finden ist.

Etwas wie folgt aus:

test_arr = [] 
with open(fileName, 'r') as file: 
    for line in file: 
     if line.startswith('---') and 'section1' in line: 
      break 

    for line in file: 
     if '---' in line: 
      break 
     fields1 = line.split(',') 
     for item in fields1: 
      testarr.append({config.get('test','test'): item}) 

with open(test_dir,'w') as test_file: 
    json.dump(testarr, test_file) 

EDIT:

Unter @ tripleee Rat habe ich die Regex Prüfung für die Startlinie entfernt. Während regex eine große Präzision und Flexibilität bietet, um ein bestimmtes Muster zu finden, ist es für dieses Beispiel wirklich übertrieben. Ich möchte darauf hinweisen, dass Sie, wenn Sie nach einem anderen Abschnitt als Abschnitt1 suchen, oder wenn Abschnitt1 nach einigen anderen Zeilen mit Bindestrichen angezeigt wird, diesen Zwei-Schleifen-Ansatz unbedingt benötigen. Die One-Loop-Lösungen in den anderen Antworten funktionieren nicht in einem nicht-trivialen Fall.

+0

Während Regex eine bessere Genauigkeit bietet, um genau die Muster zu finden, die Sie wollen, sieht es in diesem Fall wie eine Komplikation und Overkill aus. – tripleee

+0

@triplee. Ich stimme dir nicht zu. Ich habe bemerkt, dass die Zwei-Schleifen-Lösung notwendig ist, wenn Sie nach einem anderen Abschnitt als Abschnitt1 suchen, oder wenn Abschnitt1 nicht der erste Abschnitt ist. –

Verwandte Themen