Chciałbym użyć automatyzacji do stworzenia konfiguracji hocon za pomocą skryptów Pythona 3. Czytałem, że lightbend (https://github.com/lightbend/config) poleca pyhocon (https://github.com/chimpler/pyhocon).

Mam problemy ze zrozumieniem, jak utworzyć obiekt Hocon i zapisać dane do pliku jako hocon. Ważne jest dla mnie, aby w wyniku otrzymano składnię podstawienia.

Na przykład oczekuję, że wynik pliku myconfig.conf będzie wyglądał mniej więcej tak:

{
   Environment: "dev"
   JobName: ${Environment}"-hello-bob"
}

Więc założyłem, że istnieje sposób na zrobienie czegoś takiego:

config2 = ConfigFactory.parse_string("{}")
config2.put("Environment", "dev")
#Some type of object for references or special syntax for ${Environment}  
config2.put("JobName", "${Environment}")

Następnie po utworzeniu wypchanego obiektu powinien być prosty sposób na zapisanie do pliku lub plików:

filename = "myconfig.conf"
print("Write to disk as {}".format(filename))
with open(filename, "w") as fd:
    fd.write(config2.to_hocon_str)

Czy ktoś wymyślił sposób, aby to zrobić? Wydaje się dziwne, że biblioteka może być używana tylko do odczytu danych.

4
pitchblack408 20 grudzień 2019, 01:13

2 odpowiedzi

Najlepsza odpowiedź

Postanowiłem więc zajrzeć do dokumentacji biblioteki JVM (Java/Scala) (https://github.com/lightbend /config). Po przeczytaniu dokumentacji pojawiła się przejrzysta sekcja dotycząca przykładów hoconów (https://github. com/lightbend/config#examples-of-hocon). W tej dokumentacji skategoryzowali 7 prawidłowych stylów hokonów. Nazywam te style, ponieważ gdybym miał zautomatyzować generowanie tych plików, wybrałbym jeden sposób na pisanie i trzymałby się go.

Wszystko to jest zgodne z HOCON.

1. Zacznij od prawidłowego JSON:

{
    "foo" : {
        "bar" : 10,
        "baz" : 12
    }
}

2. Upuść aparat ortodontyczny:

"foo" : {
    "bar" : 10,
    "baz" : 12
}

3. Upuść cytaty:

foo : {
    bar : 10,
    baz : 12
}

4.Użyj = i pomiń go przed {:

foo {
    bar = 10,
    baz = 12
}

5. Usuń przecinki:

foo {
    bar = 10
    baz = 12
}

6. Użyj notacji z kropkami dla kluczy niecytowanych:

foo.bar=10
foo.baz=12

7. Umieść pola z kropkami w jednym wierszu:

foo.bar=10, foo.baz=12

Ponieważ będę używał biblioteki pyhocon, musiałem poszukać rozwiązań zapisu w bibliotece. Znalazłem pomoc z gita chimplera (https://github.com/chimpler/pyhocon). Odkryłem, że mają dwa style hokonów, które można po prostu napisać. Jeden to json, a drugi to coś, czego nie było na liście, która została opisana powyżej przez lightbend.

Styl 1: czysty JSON, który można zapisać na dwa sposoby:

HOCONConverter.to_json

#Using HOCONConverter.to_json
confTree = ConfigFactory.parse_string("{}")
confTree.put("Environment","Dev")
confTree.put("Test","${Environment}")

filename = "./json_coverted.conf"
print("Write to disk as {}".format(filename))
with open(filename, "w") as fd:
    fd.write(HOCONConverter.to_json(confTree))

HOCONConverter.to_json Wynik

{
    "Environment": "Dev",
    "Test": "${Environment}"
}

LUB Korzystanie z json.dump

#Using json.dump
confTree = ConfigFactory.parse_string("{}")
confTree.put("Environment","Dev")
confTree.put("Test","${Environment}")
filename = "./json_dumped.conf"
print("Write to disk as {}".format(filename))
with open(filename, "w") as fd:
    fd.write(json.dumps(confTree,indent=4))

Korzystanie z json.dump Wynik

{
  "Environment": "Dev",
  "Test": "${Environment}"
}

Inny styl Pyhocon, nie wymieniony przez lightbend

# HOCONConverter.to_hocon
confTree = ConfigFactory.parse_string("{}")
confTree.put("Environment","Dev")
confTree.put("Test","${Environment}")
filename = "./hocon_coverted.txt"
print("Write to disk as {}".format(filename))
with open(filename, "w") as fd:
    fd.write(HOCONConverter.to_hocon(confTree))

Inny styl Pyhocon, nie wymieniony przez Lightbend Result

Environment = "Dev"
Test = "${Environment}"

Tak więc, aby odpowiedzieć na moje własne pytanie, jedynym niezawodnym sposobem dynamicznego generowania pliku hocon conf przy użyciu pyhocon w Pythonie 3 jest użycie jednej z metod json (konwertera lub zrzutów). Ale to wciąż pozostawia otwarte pytanie. Pytanie brzmi, czy odczytywanie json do obiektu ConfTree pyhocon będzie w stanie wyłuskać podstawienia, gdy są one w json?

Na przykład, jeśli przeczytam plik

{
    "Environment": "Dev",
    "Test": "${Environment}"
}

Czy obiekt ConfTree otrzyma „Dev” jako wartość dla Testu?
Nie, nie będzie. Oto mój test

filename = "json_coverted.conf"
print("Reading file{}".format(filename))
conf = ConfigFactory.parse_file(filename)
key="Test"
value=conf.get(key)
print("Key:{} Value:{}".format(key,value))

Wynik testu na ekranie

Reading filejson_coverted.conf
Key:Test Value:${Environment}

Jak więc używać pyhocon z podstawieniami?

Po prostu nie może stąd, nie będę używał żadnej biblioteki do pisania confs. Musi to być proces ręczny, jeśli chcę użyć podstawień. Tak więc używam tej biblioteki tylko do czytania confs.

2
pitchblack408 21 listopad 2021, 07:24

Prawdopodobnie ten przykład odpowie na Twoje pytanie

from pyhocon.converter import HOCONConverter
import pyhocon

string = '{"Environment": "Dev","Test": ${Environment}}'
factory = pyhocon.ConfigFactory.parse_string(string, resolve=True)
factory.put('somekey','somevalue')
print(HOCONConverter().to_hocon(factory))

Zwroty

Environment = "Dev"
Test = "Dev"
somekey = "somevalue"
2
Pozdniakov Filipp 5 październik 2020, 14:46
Nie szukałem danych wyjściowych w formacie pliku właściwości.
 – 
pitchblack408
21 listopad 2021, 07:20