[Python] TOML kit로 주석 보존하면서 toml파일 수정하기

김유정·2022년 2월 10일
0
post-thumbnail

TOML kit란?

TOML kit는 파이썬을 위한 TOML 라이브러리이다.
주석, 들여쓰기, 공백 및 내부 요소의 순서를 보존하고, API를 통해 접근하거나 편집할 수 있다. 또한 새 TOML 문서를 처음부터 작성할 수 있다.

TOML 파일 수정하기

config.toml 파일이 있다. 그 중에 owner 테이블에서 name의 값을 yujung으로 바꿔보려 한다. 이 파일에는 # This is a TOML document 과 같은 주석이 있다. 이 주석을 보존하면서 수정할 것이다.

코드

from tomlkit import dump, load

# 파일 경로
cfg_path = './config.toml'

def update_config():
    with open(cfg_path, 'r') as f:   # 읽기 모드로 파일 열기
        data = load(f)               # 파일 객체를 TOMLDocument객체로 변환
    data["owner"]["name"] = "yujung" # 데이터 수정
    with open(cfg_path, 'w') as f:   # 쓰기 모드로 파일 열기
        dump(data, f)                # 수정한 데이터 저장

update_config()

파일 불러오기

data = load(f)
load는 with open(cfg_path, 'r') as f: 으로 얻게 된 파일 객체 f 를 TOMLDocument 객체로 변환해준다.

  • api
    tomlkit모듈의 api.py 파일에 load()는 다음과 같이 정의되어 있다.
def load(fp: IO) -> TOMLDocument:
    """
    Load toml document from a file-like object.
    """
    return parse(fp.read())
  • 주의해야할 점
    load는 loads와는 다르다.
    loads는 string을 TOMLDocument 객체로 변환해주는 것이기 때문에 상황에 맞게 사용해야한다.
def loads(string: Union[str, bytes]) -> TOMLDocument:
    """
    Parses a string into a TOMLDocument.
    Alias for parse().
    """
    return parse(string)

데이터 저장하기

dump(data, f)
dump는 data["owner"]["name"] = "yujung"로 수정한 data를 config.toml 파일에 복사한다.

  • api
def dump(data: Mapping, fp: IO[str], *, sort_keys: bool = False) -> None:
    """
    Dump a TOMLDocument into a writable file stream.
    :param data: a dict-like object to dump
    :param sort_keys: if true, sort the keys in alphabetic order
    """
    fp.write(dumps(data, sort_keys=sort_keys))

config.toml 파일을 읽기 권한과 쓰기 권한으로 나눠서 열어야 하는 이유

글을 읽다보면 한 가지 의문이 들 수도 있을 것이다.
굳이 'r'권한으로 파일을 열어서 데이터를 수정하고, 'w'권한으로 열어서 데이터를 저장해야하나?
그냥 r+w+ 모드로 한 번에 수정하고 저장하는 게 더 좋지않나?

def update_config():
    with open(cfg_path, 'r+') as f:
        data = load(f)
	    data["owner"]["name"] = "yujung"
        dump(data, f)

처음에 한 번에 수정과 저장을 하기 위해 다양한 방법을 시도해봤지만, 모두 문제가 발생했다.

  • r+ 모드일 경우
    r+의 경우 기존 파일에 있던 데이터를 그대로 두고 내용을 추가한다.
    파일을 읽어오는 것까지는 잘된다. 하지만 수정한 후에 dump를 하게되면, 아래와 같이 내용이 반복될 것이다.
  • w+ 모드일 경우
    w+의 경우 기존 파일에 있던 데이터를 삭제하고 내용을 입력한다.
    데이터가 삭제되기 때문에 데이터를 불러오는 과정에서 문제가 발생한다.
    tomlkit.exceptions.NonExistentKey: 'Key "owner" does not exist.'

결과적으로, 파일을 수정할 경우에는 읽기 모드로 파일을 연 후에 수정하고, 쓰기 모드로 파일을 연 후에 저장해야한다.

TOML 파일 만들기

이번에는 기존에 있는 파일을 수정하는 게 아니라 새로운 TOML 파일을 만들어볼 것이다.

코드

from tomlkit import comment, dump, document, nl, table

cfg_path = './config2.toml'

# 파일 만들기
def create_config():
    doc = document()   # TOMLDocument 객체 만들기
    doc.add(comment("This is a TOML document."))   # 주석 추가하기
    doc.add(nl())   # 줄바꿈
    doc.add("title", "TOML Example")

    owner = table()   # 테이블 만들기
    owner.add("name", "Tom Preston-Werner")   # 데이터 추가하기
    owner.add("organization", "GitHub")
    owner["organization"].comment("주석 보존 확인")   # 주석 달기

    doc.add("owner", owner)

    database = table()   # 테이블 만들기
    database["server"] = "192.168.1.1"   #데이터 추가하기
    database["ports"] = [8001, 8001, 8002]
    database["connection_max"] = 5000
    database["enabled"] = True

    doc["database"] = database

    with open(cfg_path, "w") as f:   # 쓰기 모드로 파일 열기
        dump(doc, f)

create_config()

TOMLDocument 객체 만들기

doc = document()

주석 추가하기

원하는 테이블의 컬럼에 주석을 달 수 있다.
테이블이름["컬럼이름"].comment("주석 내용")

데이터 추가하기

추가하는 방법은 두가지가 있다.
1) 테이블.add("key 값", "value 값")
2) 테이블["key 값"] = "value 값"

원하는 테이블을 만들고 데이터들을 추가했으면 open으로 파일을 열어서 저장하면 된다.
("w"모드는 파일이 없을 때 파일을 생성한다.)

참고

0개의 댓글