2017-06-12 3 views
2

Ich versuche, in eine XYZ-Datei in Python lesen, aber diese Fehlermeldungen erhalten. Ein bisschen neu zu Python, also würde einige Hilfe lieben es zu interpretieren!Lesen von Datei mit Variablenspalten

def main(): 
    atoms = [] 
    coordinates = [] 
    name = input("Enter filename: ") 
    xyz = open(name, 'r') 
    n_atoms = xyz.readline() 
    title = xyz.readline() 
    for line in xyz: 
     atom, x, y, z = line.split() 
     atoms.append(atom) 
     coordinates.append([float(x), float(y), float(z)]) 
    xyz.close() 

    return atoms, coordinates 


if __name__ == '__main__': 
    main() 

Error: 
Traceback (most recent call last): 
    File "Project1.py", line 25, in <module> 
    main() 
    File "Project1.py", line 16, in main 
    atom, x, y, z = line.split() 
ValueError: not enough values to unpack (expected 4, got 3) 

glaube ich, der Wert Fehler ist, weil nach ein paar Zeilen nur 3 Werte sind. Aber ich bin mir nicht sicher, warum ich Fehler bei der Rückgabe bekomme.

Antwort

2

Eine sehr wichtige Faustregel vor allem in Python ist: Das Rad nicht neu erfinden und vorhandene Bibliotheken verwenden.

Die xyz-Dateien sind eines der wenigen universell genormten Dateiformate in der Chemie. Also IMHO brauchen Sie keine Logik, um die Länge Ihrer Linie zu bestimmen. Die erste Zeile ist eine Ganzzahl und gibt Ihnen die Anzahl der Atome, die zweite Zeile ist eine ignorierte Kommentarzeile und die nächsten Zeilen sind [string, float, float, float] wie Sie bereits in Ihrem Code geschrieben haben. Eine Datei, die davon abweicht, ist wahrscheinlich beschädigt.

Mit dem pandas library können Sie einfach schreiben:

import pandas as pd 
molecule = pd.read_table(inputfile, skiprows=2, delim_whitespace=True, 
         names=['atom', 'x', 'y', 'z']) 

Oder Sie verwenden die chemcoord Paket, das seine eigene cartesianischen Klasse Moleküle in kartesischen Koordinaten darstellen:

import chemcoord as cc 
molecule = cc.Cartesian.read_xyz(inputfile) 

Disclaimer: Ich bin der Autor von chemcoord.

+0

Vielen Dank! Ich werde definitiv Bibliotheken in der Zukunft untersuchen! – Camerann

0

Sie erhalten Fehler, weil Sie eine Liste in der

Linie entpacken
atom, x, y, z = line.split() 

Das macht nur Sinn, wenn es 4 Elemente in der Linie sind.

Sie haben Logik zu definieren, was passiert, wenn es nur 3 Elemente in einer Linie, wie folgt aus (in der for Schleife):

for line in xyz: 
    line_data = line.split() 
    if len(line_data) == 3: 
     # Behavior when only 3 items in a line goes here! 
     # Add your code here! 
     continue 

    atom, x, y, z = line_data 
    atoms.append(atom) 
    coordinates.append([float(x), float(y), float(z)]) 

Was Ihr Programm tut, wenn es eine Zeile mit nur 3 Begegnungen Artikel hängt davon ab, was Sie wollen.

+0

Es wäre wahrscheinlich gut, auch nach dem Fall 'len (line_data) == 4' zu suchen –

+0

@ cricket_007 Der Fall' == 4' ist bereits implementiert. Wenn die Länge weder 3 noch 4 ist, wird das Programm (korrekt) abstürzen, wodurch der Programmierer gewarnt wird, dass Code für das neue Format (z. B. 5 Elemente) hinzugefügt werden muss. – phihag

+0

Ich würde die Liste nur auf 4 Elemente entpacken 'falls len (line_data) == 4'. Andernfalls melden Sie das unerwartete Format "len (line_data)! = 4". Ich finde komisch, nur auf das unerwartete Format 3, und lasse das Programm auf 5,6,7,8 usw. abstürzen ... – JoonasS