在 python 中读取 YAML 文件时出错
Error while reading YAML file in python
我有一个 yaml
文件,如下所示:
%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 ]
它基本上是一个 opencv matrix
,我用 c++
代码创建了文件。现在我想在 python
中读取这个文件,我有这个代码:
import yaml
with open("reference_3d.yml") as fin:
rfr = yaml.load(fin.read())
但是当我 运行 代码时,它给我这个错误:
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
^
知道我应该如何解决这个错误吗?
这里的问题是您的 C++ 生成(无效的)YAML 1.0,并且您尝试使用可以处理大部分 YAML 1.1 的 Python 解析器来解析它。
YAML 1.0 specification doesn't have many examples, but the directive for documents states that the optional c-ns-directive should come in the document header after the document start (rules 48 and 49) and the specification clearly states that its form should be %YAML:1.0
。因此,正确的 YAML 1.0 文档应以:
开头
---
%YAML:1.0
然而,即使输出正确,PyYAML 也无法读取这个旧的 YAML 版本文件。
由于最新的 YAML 规范 (1.2) 是从 2009 年开始的,您最好的办法是将您的 C++ 程序和 Python 程序都切换到 1.2 兼容的库库。关于 yaml.org it is indicated that for C++ this would be yaml-cpp
and for Python this would have to be ruamel.yaml
(免责声明:我是该软件包的作者)。
YAML 文件看起来像(yaml-cpp
可能会更改标签,甚至可能会更改转储的其余部分):
%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 ]
你可以这样做:
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])
获取第一个数据行的最后一个值(416.388153
)
如果您不能或不愿意更改您的 C++ 程序,则只需使用 ruamel.yaml
并跳过 YAML 文件的第一行:
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])
我有一个 yaml
文件,如下所示:
%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 ]
它基本上是一个 opencv matrix
,我用 c++
代码创建了文件。现在我想在 python
中读取这个文件,我有这个代码:
import yaml
with open("reference_3d.yml") as fin:
rfr = yaml.load(fin.read())
但是当我 运行 代码时,它给我这个错误:
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
^
知道我应该如何解决这个错误吗?
这里的问题是您的 C++ 生成(无效的)YAML 1.0,并且您尝试使用可以处理大部分 YAML 1.1 的 Python 解析器来解析它。
YAML 1.0 specification doesn't have many examples, but the directive for documents states that the optional c-ns-directive should come in the document header after the document start (rules 48 and 49) and the specification clearly states that its form should be %YAML:1.0
。因此,正确的 YAML 1.0 文档应以:
---
%YAML:1.0
然而,即使输出正确,PyYAML 也无法读取这个旧的 YAML 版本文件。
由于最新的 YAML 规范 (1.2) 是从 2009 年开始的,您最好的办法是将您的 C++ 程序和 Python 程序都切换到 1.2 兼容的库库。关于 yaml.org it is indicated that for C++ this would be yaml-cpp
and for Python this would have to be ruamel.yaml
(免责声明:我是该软件包的作者)。
YAML 文件看起来像(yaml-cpp
可能会更改标签,甚至可能会更改转储的其余部分):
%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 ]
你可以这样做:
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])
获取第一个数据行的最后一个值(416.388153
)
如果您不能或不愿意更改您的 C++ 程序,则只需使用 ruamel.yaml
并跳过 YAML 文件的第一行:
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])