Συγχώνευση hashes σε YAML αρχεία conf

31ης Ιουλίου, 2009 από Prashant · Σχόλια
Filed under: τεχνολογία

YAML είναι αρκετά βολικό για τη γραφή αρχεία ρυθμίσεων. Πρωτοβάθμια πλεονέκτημα είναι ότι, διαβάζει σαν αρχείο κειμένου. Αυτό λειτουργεί πολύ καλά, αν config αρχείο σας είναι επίπεδος (χωρίς ιεραρχία) και δεν έχει καμία επαναλήψεις.
Αν διαμορφώσεις το αρχείο σας έχει επαναλήψεις τότε είναι λογικό να διαχωριστούν από εκείνα τα στοιχεία και την επαναχρησιμοποίηση τους. Αυτό που εννοώ είναι αυτό - ας πούμε ότι έχετε το αρχείο επιλογών σας μοιάζει με αυτό:

  ανάπτυξη:
   input_location: common_input
   output_location: dev_location
   mail:
     smtp_server: your_server
     Είσοδος: your_login
     Κωδικός πρόσβασης: top_secret
 παραγωγή:
   input_location: common_input
   output_location: dev_location
   mail:
     smtp_server: your_server
     Είσοδος: your_login
     Κωδικός πρόσβασης: top_secret 

Υποθέτοντας παραπάνω κώδικα στο / tmp / test.yml εδώ είναι το πώς μπορείτε να διαβάσετε στην Python και Ruby
$cat readyml.py

 #! / Usr / bin / env python
 από pprint εισαγωγή pprint ως pp
 # Σε debian πρέπει να εγκαταστήσετε python-YAML
 από το φορτίο εισαγωγής YAML, load_all, χωματερή
 hash = φορτίο (open ("/ tmp / test.yml '))
 PP (hash [«ανάπτυξη»]) 


$ cat readyml.rb

  #! / Usr / bin / env ρουμπίνι
 απαιτούν «PP»
 hash = YAML:: φορτίο (File.open ('/ tmp / test.yml ») το διαβάσετε.)
 PP hash [«ανάπτυξη»] 

Εδώ είναι ένα εύχρηστο μία επένδυση για το ρουμπίνι έκδοση
$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]' ή μπορείτε να δοκιμάσετε την ίδια σε IRB ή python κονσόλα.

Σημειώνεται ότι στο παραπάνω απόσπασμα κώδικα, τα πάντα είναι εκτός θέσης εξόδου είναι ίδιο εν μέρει την ανάπτυξη και την παραγωγή. Αυτό είναι όπου YML αναγνωριστικό κόμβος έρχεται να σώσει. Η ιδέα είναι απλή έχουν μια σειρά από προκαθορισμένες τιμές και παρακάμπτουν τους σε διαφορετικό μέρος.
Θα μπορούσατε να το κάνω κομμάτια ως εξής:

  προεπιλογές: & προεπιλογές
   input_location: common_input
   output_location: dev_location
   mail:
     SENDER_NAME: αποστολέα
     smtp_server: your_server
     Είσοδος: your_login
     Κωδικός πρόσβασης: top_secret
 ανάπτυξη:
   <<: * Προεπιλογές
 παραγωγή:
   <<: * Προεπιλογές
   output_location: prod_location 


$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]["mail"]["login"]'
"your_login"
$

Μεγάλη, λειτουργεί (tm)!.
Βεβαίως, εμείς διαπραγματεύονται κάποια σαφήνεια για ένα κομμάτι της μαγείας. Εδώ είναι μια μικρή εξήγηση: &, * και <<: και η οποία είναι ετικέτα άγκυρα μπορεί να θεωρηθεί ως κόμβος αναγνωριστικό, * είναι κόμβος αναφοράς και <<: σημαίνει hash συγχώνευση.

Για περισσότερες λεπτομέρειες, βλ. είτε YAML specs ή wikipedia
Μέχρι εδώ καλά, αλλά υπάρχει ένα πρόβλημα εδώ, αυτά τα hash συγχωνεύει δεν είναι αναδρομική. Αυτό που σημαίνει είναι το εξής: ας υποθέσουμε ότι θέλετε να έχετε διαφορετικό όνομα αποστολέα για αλληλογραφία σε δύο περιβάλλοντα, μπορείτε να μπείτε στον πειρασμό να κάνετε τα εξής:

  προεπιλογές: & προεπιλογές
   input_location: common_input
   output_location: dev_location
   mail:
     SENDER_NAME: αποστολέα
     smtp_server: your_server
     Είσοδος: your_login
     Κωδικός πρόσβασης: top_secret
 ανάπτυξη:
   <<: * Προεπιλογές
   mail:
     SENDER_NAME: sender_dev
 παραγωγή:
   <<: * Προεπιλογές
   output_location: prod_location
   mail:
     SENDER_NAME: sender_prod 

Αφήνει να ελέγξετε

$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]["mail"]["login"]'
nil
$

Ωχ, κάτι πήγε στραβά, το πρόβλημα όπως προαναφέρθηκε είναι ότι το hash συγχώνευση δεν έχει επαναληπτικό και ενώ η συγχώνευση θα αντικατασταθεί ταχυδρομείου αθέτησης των υποχρεώσεων του ταχυδρομείου της παραγωγής, η οποία έχει μόνο ένα κλειδί. Λύση / αντιμετωπίσετε είναι να επεκταθούν ένα ακόμη επίπεδο:

  common_settings: & common_settings
 input_location: common_input
 output_location: dev_location
 mail_defaults: & mail_defaults
  SENDER_NAME: αποστολέα
   smtp_server: your_server
   Είσοδος: your_login
   Κωδικός πρόσβασης: top_secret

 προεπιλογές: & προεπιλογές
   <<: * Common_settings
   mail:
     <<: * Mail_defaults
 ανάπτυξη:
   <<: * Προεπιλογές
 παραγωγή:
   <<: * Προεπιλογές
   mail:
     <<: * Mail_defaults
     SENDER_NAME: sender_prod

Αφήνει να ελέγξετε και πάλι

$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]["mail"]["login"]'
"your_login"
$

Μήπως λέτε ότι έχετε ένα ακόμα επίπεδο ένθεσης, και μπορείτε να επεκταθούν σίγουρα ένα ακόμη επίπεδο, αλλά στη συνέχεια γίνεται ένα χάος. Έτσι, εάν δεν προσπαθείτε να γράψει λύση με τους πύργους του Ανόι σε ένα conf αρχείο, είναι καλύτερα να restucture conf αρχείο από το σκάψιμο σε YAML ή κάτι άλλο. Αλλά αυτό είναι η κλήση σας ούτως ή άλλως.