2012-11-08 11 views
7

In primo luogo, un disclaimer: non ho molta familiarità con YAML. Sto cercando di analizzare un documento YAML in coppie di valori chiave (. Non preoccupatevi di come lo sto facendo io ho quel po 'gestito)errori pyYAML su "!" in una stringa

mio file utilizzato per cercare qualcosa di simile:

world: 
    people: 
      name:Suzy 
      address:chez-bob 

Poi, qualcuno è andato a cambiarlo.

world: 
    people: 
      name:!$uzy 
      address:chez-bob 

e ottengo questo errore di analisi:

yaml.constructor.ConstructorError: could not determine a constructor for the tag '!$uzy' 

Cosa ancora significa? Come potrei fare per interpretarlo! $ Come solo due personaggi? Voglio solo un dizionario di chiavi e valori di stringa! Inoltre, la modifica dei file yaml non è un'opzione. Il problema deve essere risolto nel codice utilizzando il parser.

+0

Quindi sì, mi rendo conto ora che il! dice di costruire un $ uzy, tuttavia, il contenuto del file non è la mia preoccupazione. Gestirlo in modo elegante è. Quello che voglio che faccia è trattare! $ Uzy come testo. – Rokujolady

+0

... anche, NON UTILE. – Rokujolady

risposta

8

Punto esclamativo è un prefisso per i tag YAML. Il parser deve implementare un costruttore per il nome del tag. Esistono alcuni tag predefiniti come !!bool, !!int, ecc. E persino alcuni tag specifici di Python come !!python/tuple.

È possibile definire i propri costruttori e persino i costruttori per più tag catturati da un prefisso. Definendo il prefisso allo '', è possibile catturare tutti i tag e ignorarli. Puoi restituire il tag e il suo valore dal costruttore per considerare tutto come testo.

>>> import yaml 
>>> def default_ctor(loader, tag_suffix, node): 
...  print loader 
...  print tag_suffix 
...  print node 
...  return tag_suffix + ' ' + node.value 
... 
>>> yaml.add_multi_constructor('', default_ctor) 
>>> yaml.load(y) 
<yaml.loader.Loader object at 0xb76ce8ec> 
!$uzy 
ScalarNode(tag=u'!$uzy', value=u'') 
{'world': {'people': {'name': '!$uzy', 'address': 'chez-bob'}}} 
>>> 
+0

Potresti fornire un esempio più dettagliato, avere un problema simile [qui] (http://stackoverflow.com/questions/43081483/write-a-constructor-to-handle-specific-tags-in-ruamel-or- pyyaml) – askb

4

Se un valore inizia con "!", È necessario racchiudere il valore tra virgolette singole o doppie; altrimenti viene interpretato come un tag YAML.

world: 
    people: 
      name: "!$uzy" 
      address: chez-bob 
0

Questo è in realtà un bug in PyYAML. Interpreta lo : in name:!$uzy come separatore di chiave/valore, ma dovrebbe farlo solo se : è seguito da uno spazio o se viene quotato lo scalare precedente (name). L'errore di follow-up è che il punto esclamativo, che dovrebbe essere consentito nel mezzo di uno scalare, viene erroneamente interpretato come all'inizio di uno scalare e quindi introduce un tag.

Il valore per la chiave people è la stringa name:!$uzy address:chez-bob e viene gestita correttamente in altri parser (incluso il pacchetto Python ruamel.yaml di cui sono l'autore).

+0

Sembra che una soluzione per questo sia stata incorporata nei sorgenti di PyYAML all'inizio del 2017. Ma poiché l'ultima versione era agosto 2016 e quella precedente a marzo 2014, potrebbero essere necessari alcuni mesi/anni prima che questa sia disponibile su PyPI. – Anthon