2017-03-18 4 views
1

Ich habe eine yaml-Datei, die wie folgt aussieht:Fehler beim YAML-Datei in Python zu lesen

%YAML 1.0 
temp: !!opencv-matrix 
rows: 2 
cols: 23 
dt: f 
data: [ 3.35620789e+02, 3.64299591e+02, 3.95790131e+02, 
    4.39863068e+02, 4.68664948e+02, 4.93518127e+02, 4.17159943e+02, 
    4.21060364e+02, 3.99990234e+02, 4.17867157e+02, 4.34151215e+02, 
    3.56201202e+02, 3.77741028e+02, 3.87051544e+02, 3.76879913e+02, 
    4.42746796e+02, 4.52483917e+02, 4.73469604e+02, 4.52954742e+02, 
    3.78402283e+02, 4.17679047e+02, 4.50588501e+02, 4.16388153e+02, 
    9.05276794e+01, 9.21245193e+01, 1.02799362e+02, 9.93146744e+01, 
    8.40704346e+01, 7.84236526e+01, 1.15820358e+02, 1.76747055e+02, 
    1.61153061e+02, 1.68130676e+02, 1.58446228e+02, 1.07421455e+02, 
    1.03407494e+02, 1.05380608e+02, 1.08374542e+02, 1.01048920e+02, 
    9.76309204e+01, 9.83933716e+01, 1.02486870e+02, 1.71890350e+02, 
    1.81417206e+02, 1.66303802e+02, 1.95539871e+02 ] 

Es ist im Grunde ein opencv matrix und ich habe die Datei in einem c++ Code erstellt. Jetzt möchte ich diese Datei in python lesen und ich habe diesen Code:

import yaml 
with open("reference_3d.yml") as fin: 
    rfr = yaml.load(fin.read()) 

Aber wenn ich den Code ausführen, es gibt mir diese Fehlermeldung:

Traceback (most recent call last): 
File "scatter_plot.py", line 15, in <module> 
rfr = yaml.load(fin.read()) 
File "/usr/local/lib/python2.7/site-packages/yaml/__init__.py", line 71, in load 
return loader.get_single_data() 
File "/usr/local/lib/python2.7/site-packages/yaml/constructor.py", line 37, in get_single_data 
node = self.get_single_node() 
File "/usr/local/lib/python2.7/site-packages/yaml/composer.py", line 35, in get_single_node 
if not self.check_event(StreamEndEvent): 
File "/usr/local/lib/python2.7/site-packages/yaml/parser.py", line 98, in check_event 
self.current_event = self.state() 
File "/usr/local/lib/python2.7/site-packages/yaml/parser.py", line 157, in parse_implicit_document_start 
return self.parse_document_start() 
File "/usr/local/lib/python2.7/site-packages/yaml/parser.py", line 174, in parse_document_start 
self.peek_token().start_mark) 
yaml.parser.ParserError: expected '<document start>', but found '<scalar>' 
in "<string>", line 2, column 2: 
temp: !!opencv-matrix 
^ 

Jede Idee, wie soll ich diesen Fehler beheben ?

+0

@karthikr Bitte seien Sie vorsichtig, Fragen als Duplikat zu schließen. Die Unterschiede zwischen der YAML-Datei in der Frage, die Sie als Duplikat angeben, und der Datei in dieser Frage und den anderen Umständen sind subtil, aber signifikant. Es gibt einen besseren Weg, als eine Axt zu nehmen und die ersten beiden Zeilen zu schneiden, um ** diese ** Frage zu lösen, die nicht für die gilt, die Sie als Duplikat angeben. Eine mögliche Antwort kann also nur hier sein und kann nicht beim Duplikat hinzugefügt werden. – Anthon

Antwort

2

Das Problem hier ist, dass Ihr C++ (ungültig) YAML 1.0 generiert und Sie versuchen, das mit einem Python-Parser zu analysieren, der die meisten von YAML 1.1 verarbeiten kann.

Die YAML 1.0 specification hat nicht viele Beispiele, aber die Richtlinie für Dokumente besagt, dass die optionalen c-ns-directiveclearly states that its form should be %YAML:1.0 im Belegkopf nach dem Dokument Start (rules 48 and 49) und die Beschreibung kommen sollte. Daher ist ein korrektes YAML 1.0 Dokument sollte beginnen mit:

--- 
%YAML:1.0 

Doch selbst wenn dies korrekt ausgegeben würde PyYAML nicht in der Lage sein, diese ältere Version YAML-Datei zu lesen.

Da die neueste YAML-Spezifikation (1.2) aus dem Jahr 2009 stammt, sollten Sie sowohl Ihr C++ - Programm als auch Ihr Python-Programm in eine 1.2-kompatible Bibliotheksbibliothek umwandeln. Auf yaml.org wird angezeigt, dass dies für C++ yaml-cpp wäre und für Python wäre dies ruamel.yaml (Disclaimer: Ich bin der Autor dieses Pakets).

Die YAML-Datei aussehen wird (yaml-cpp könnte den Tag ändern und vielleicht sogar den Rest der Halde):

%YAML 1.2 
--- 
temp: !!opencv-matrix 
rows: 2 
cols: 23 
dt: f 
data: [ 3.35620789e+02, 3.64299591e+02, 3.95790131e+02, 
    4.39863068e+02, 4.68664948e+02, 4.93518127e+02, 4.17159943e+02, 
    4.21060364e+02, 3.99990234e+02, 4.17867157e+02, 4.34151215e+02, 
    3.56201202e+02, 3.77741028e+02, 3.87051544e+02, 3.76879913e+02, 
    4.42746796e+02, 4.52483917e+02, 4.73469604e+02, 4.52954742e+02, 
    3.78402283e+02, 4.17679047e+02, 4.50588501e+02, 4.16388153e+02, 
    9.05276794e+01, 9.21245193e+01, 1.02799362e+02, 9.93146744e+01, 
    8.40704346e+01, 7.84236526e+01, 1.15820358e+02, 1.76747055e+02, 
    1.61153061e+02, 1.68130676e+02, 1.58446228e+02, 1.07421455e+02, 
    1.03407494e+02, 1.05380608e+02, 1.08374542e+02, 1.01048920e+02, 
    9.76309204e+01, 9.83933716e+01, 1.02486870e+02, 1.71890350e+02, 
    1.81417206e+02, 1.66303802e+02, 1.95539871e+02 ] 

Und das können Sie tun:

from ruamel import yaml 

with open('reference_3d.yml') as fin: 
    rfr = yaml.round_trip_load(fin) 

print(rfr['temp']['data'][rfr['temp']['cols']-1]) 

die letzten zu bekommen Wert der ersten Datenzeile (416.388153)

Wenn Sie Ihr C++ - Programm nicht ändern können oder wollen, verwenden Sie einfach ruamel.yaml und s kip die erste Zeile der YAML-Datei:

from ruamel import yaml 

with open('reference_3d.yml') as fin: 
    fin.readline() 
    rfr = yaml.round_trip_load(fin) 

print(rfr['temp']['data'][rfr['temp']['cols']-1])