2015-01-21 5 views
2

Я знаком с подобными вопросами, но они, похоже, не затрагивают то, что должно быть простой проблемой. Я использую Python 2.7x и пытается прочитать YAML файл, который выглядит примерно так:Как пропустить строки при чтении файла yaml в python?

%YAML:1.0 
radarData: !!opencv-matrix 
rows: 5 
cols: 2 
dt: u 
data: [0, 0, 0, 0, 0, 10, 5, 3, 1, 22] 

На данный момент мне нужно только «данные:» документ. Я пробовал ванильный подход, а затем попытался заставить пропустить первые 4 строки (второй фрагмент кода, который прокомментирован). Оба подхода дали ошибки.

import yaml 
stream = file('test_0x.yml', 'r') 
yaml.load(stream) 
# alternative code snippet 
# with open('test_0x.yml') as f: 
# stream = f.readlines()[4:] 
# yaml.load(stream) 

Любые предложения о том, как пропустить первые несколько строк, будут очень признательны.

ответ

9

На самом деле вам нужно пропустить первые 2 строки.

import yaml 

skip_lines = 2 
with open('test_0x.yml') as infile: 
    for i in range(skip_lines): 
     _ = infile.readline() 
    data = yaml.load(infile) 

>>> data 
{'dt': 'u', 'rows': 5, 'data': [0, 0, 0, 0, 0, 10, 5, 3, 1, 22], 'cols': 2} 
>>> data['data'] 
[0, 0, 0, 0, 0, 10, 5, 3, 1, 22] 

Пропуск первых 5 линий также работает.

+0

Спасибо, что нашли время, но @mhawke находится прямо на отметке. FWIW - одна реинкарнация файла данных имеет 4 строки без ямля. Опять-спасибо! – Aengus

+0

Поклонник во мне говорит, будьте осторожны, называя строки «не-ЯМЛ». В конечном счете, если вы столкнетесь с большим количеством того, что я назвал бы «менее строгим» YAML, имеет смысл построить шаги предварительной обработки, которые будут соответствовать данным, а не полагаться на упорядочение ключей в ваших данных. Тем не менее, не фиксируйте, что не сломалось. – spirulence

1

Я полностью пропустил пункт здесь, но я оставляю свой первоначальный ответ внизу как смиряющее напоминание.

Ответ mhawke короткий и сладкий, и, вероятно, предпочтительнее. Более сложное решение: разделите эту неверную директиву, исправьте свой собственный тег и добавьте для нее конструктор. Это имеет то преимущество, что исправление этого тега везде, где оно появляется в файле, а не только в первых двух строках.

Мое выполнение здесь имеет некоторые недостатки - оно вскрывает целые файлы, и оно не было проверено на сложных данных, где эффект замены тега на соответствующий может иметь разные результаты, чем предполагалось.

import yaml 

def strip_malformed_directive(yaml_file): 
    """ 
    Strip a malformed YAML directive from the top of a file. 

    Returns the slurped (!) file. 
    """ 
    lines = list(yaml_file) 
    first_line = lines[0] 
    if first_line.startswith('%') and ":" in first_line: 
     return "\n".join(lines[1:]) 
    else: 
     return "\n".join(lines) 


def convert_opencvmatrix_tag(yaml_events): 
    """ 
    Convert an erroneous custom tag, !!opencv-matrix, to the correct 
    !opencv-matrix, in a stream of YAML events. 
    """ 
    for event in yaml_events: 
     if hasattr(event, "tag") and event.tag == u"tag:yaml.org,2002:opencv-matrix": 
      event.tag = u"!opencv-matrix" 
     yield event 


yaml.add_constructor("!opencv-matrix", lambda loader, node: None) 
with open("test_0x.yml") as yaml_file: 
    directive_processed = strip_malformed_directive(yaml_file) 
    yaml_events = yaml.parse(directive_processed) 
    matrix_tag_converted = convert_opencvmatrix_tag(yaml_events) 
    fixed_document = yaml.emit(matrix_tag_converted) 

    data = yaml.load(fixed_document) 
    print data 

Оригинал ответа

Это yaml.load функция вы используете возвращает словарь, который можно получить следующим образом:

import yaml 

with open("test_0x.yml") as yaml_file: 
    test_data = yaml.load(yaml_file) 

print test_data["data"] 

ли это помощь?

+0

Я думаю, что вам не хватает точки, которая заключается в том, что первые 2 л ines недействительны YAML и должны быть пропущены. – mhawke

+0

Ты совершенно прав. Хороший улов, и спасибо. – spirulence

0

я матрица камеры генерируется aruco_calibration_fromimages.exe, вот YML файл:

%YAML:1.0 
--- 
image_width: 4000 
image_height: 3000 
camera_matrix: !!opencv-matrix 
    rows: 3 
    cols: 3 
    dt: d 
    data: [ 3.1943912478853654e+03, 0., 1.9850941722590378e+03, 0., 
     3.2021356095317910e+03, 1.5509955246019449e+03, 0., 0., 1. ] 
distortion_coefficients: !!opencv-matrix 
    rows: 1 
    cols: 5 
    dt: d 
    data: [ 1.3952810090687282e-01, -3.8313647492178071e-01, 
     5.0555840762660396e-03, 2.3753464602670597e-03, 
     3.3952514744179502e-01 ] 

Загрузите этот YML с этим кодом:

import cv2 
fs = cv2.FileStorage("./calib_asus_chess/cam_calib_asus.yml", cv2.FILE_STORAGE_READ) 
fn = fs.getNode("camera_matrix") 
print(fn.mat()) 

И получить этот результат:

[[ 3.19439125e+03 0.00000000e+00 1.98509417e+03] 
[ 0.00000000e+00 3.20213561e+03 1.55099552e+03] 
[ 0.00000000e+00 0.00000000e+00 1.00000000e+00]] 
Смежные вопросы