본문 바로가기

Python

Python - configparser & argparser

안녕하세요 이번에는 실제 파이썬 프로그램을 실행할 때 많이 마주치게 될 configparser와 argparser에 대해서 알아보도록 하겠습니다. 그럼 시작하겠습니다. :)

개발을 하다보면 타인의 좋은 프로그램 혹은 코드를 가져다 사용하는 경우가 많다. 그런데, 해당 프로그램 혹은 코드를 그대로 가져다쓰는 것이 아니라 수정해서 사용하고 싶다면 어떻게 해야할까? 이 방법으로는 크게 두가지가 있는데 그 중 하나가 파일에 설정을 저장해두고 사용하는 configparser고, 다른 하나는 실행시점에 터미널 창에서 인자를 통해 설정을 조정해줄 수 있는 argparser다.

Configparser


프로그램 개발자들은 프로그램의 설정들을 config 파일에 저장해두고, 이러한 설정 config 파일을 읽어다가 사용함으로써 설정을 쉽게 수정할 수 있도록 하고 있다. 이를 위해서 python에서 사용하는 것이 configparser모듈이다.

config file format

configparser를 통해 parsing할 수 있는 file format은 cfg혹은 ini라는 확장자를 가지는 파일 형식이다. 즉 config.cfgconfig.ini 같은 파일을 활용하여 application의 설정을 위한 정보를 가져와 설정할 수 있다는 것이다. 이러한 파일 형식들은 아래와 같은 구조를 가진다. 

[SECTION 1]
key1 = 1
key2 : 2

[SECTION 2]
key3 = 3
key4 : 4

[SECTION 3]
key5 = 5
key6 : 6

이렇게 파일은 크게 Section들로 나뉘게 되고, 각 섹션에는 key값과 value값으로 구성된다. 이 때 Section의 구분은 [Section]처럼 []를 통해서 구분되고, key, value를 각 섹션에 적어주면 된다. 이 때 key value 쌍을 구성함에 있어서 = 을 사용해도 좋고 : 를 사용해도 좋다.

이러한 config파일은 파이썬에서 configparser라는 모듈을 통해 parsing된다. 즉 이러한 파일을 읽고 쓸 수 있는 것이다. 그렇다면 이러한 파일이 파이썬에서는 어떻게 읽힐까? 지금껏 공부해온 것을 토대로 생각해보자. 아마도 dict type일 것이다. 정답이다. 이러한 config 파일은 configparser를 통해 parsing되고 dict type처럼 처리되게 된다.

import configparser

config = configparser.ConfigParser()
config.sections()
>>>
# 빈 객체이므로 아무것도 출력되지 않는다.

config.read('config.ini')
print(config.sections())
>>> ['SECTION 1', 'SECTION 2', 'SECTION 3']
# 해당 config file을 읽은 상태이므로 출력된다.

for key in config['SECTION 1'] :
    print(key)
>>> key1
key2

즉 위와 같이 configparser객체를 만든 후에 read()를 통해 특정 config파일을 불러오게 되면 config객체에는 해당 파일이 parsing된 상태의 데이터가 들어있게 되고 이는 dict type처럼 처리된다.( 물론 세부적인 차이가 조금 있긴 하지만, 신경쓸일은 잘 없다. )

Argparser


지금까지는 config정보 설정 정보를 파일에 저장해두는 방식을 알아봤다. 이번에는 프로그램 실행시점에 config 혹은 setting 정보를 넣어주는 ( console창에서 ) argparser에 대해서 알아보도록 하겠다. 특히 Machine Learning을 하다보면 많은 옵션들이 이러한 argparser를 통해서 모델 실행시 전달되는 것을 자주 볼 수 있다. 따라서 무척 잘 알아두는 것이 좋다. 특히 AI쪽이라면 아주 많이 보게 될 것이다.

python train.py --epochs 50 --batch-size 64 --save-dir weights

위와 같이 머신러닝 모델을 학습하기 위해서 이런식으로 콘솔창에서 혹은 command창에서 python filename options 와같은 형태로 실행시키기 때문에 꼭 알아둬야한다.

이런식의 argparsing은 파이썬에서 argparse라는 라이브러리를 통해서 사용할 수 있다. argparse의 사용법은 아래와 같다. 여기서 주의할 점은 argparsing같은 경우 터미널에서 실행하는 것을 원칙으로 하기 때문에, Jupyter Notebook과 같은 대화형 framework에서 사용하기는 어렵다. 불가능한 것은 아니지만, 굳이 argparser를 사용할 이유가 없다.

import argparse

parser = argparse.ArgumentParser(description='Argparse Tutorial')
parser.add_argument('--print-number', type=int, 
                    help='an integer for printing repeatably')

args = parser.parse_args()

for i in range(args.print_number):
    print('print number {}'.format(i+1))
    


출처 : https://greeksharifa.github.io/references/2019/02/12/argparse-usage/
  1. argument를 parsing해줄 parser객체를 만든다. 이 때 이 객체가 어떤 역할을 하게 될지 즉, 어떤 목적으로 인자들을 parsing해주는지에 따라서 description을 적절히 설정한다.
  2. 해당 parser추후에 터미널을 통해서 전달해줄 인자들을 미리 정해둔다. add_argument() method를 통해서 할 수 있다. 참고로 argument의 추가는 원하는 만큼 할 수 있다.
  3. parser를 통해 parsing을 하기 위해서는 parse_args() 메소드를 사용한다. 그러면, 터미널에서 전달된 인자들이 parsing된다. 위의 코드에서는 parsing된 인자들을 args라는 변수에 할당했다. 
  4. 그러면 parsing된 인자들에 대해서 add_argument()를 할 때 정해준 argument name에 따라서 접근할 수 있게 된다.

이러한 맥락에 따라 터미널 창에서 해당 파일을 실행시켜보면서 argument를 직접parsing해볼 수 있다. 해당 예시는 단순히 int를 반복적으로 출력하기 위한 코드다.

> python argparseTest.py --print-number 5
print number 1
print number 2
print number 3
print number 4
print number 5

출처 : https://greeksharifa.github.io/references/2019/02/12/argparse-usage/

참고로 --help혹은 -h와 같은 옵션을 추가함으로써, 해당 py파일에서 argparsing시 parsing되는 각 argument에 대한 도움말을 얻을 수 있다. ( 우리가 argument를 추가할 때 미리 정해둔 help에 적힌 명령어가 출력된다. )

> python argparseTest.py -h
usage: argparseTest.py [-h] [--print-number PRINT_NUMBER]

Argparse Tutorial

optional arguments:
  -h, --help            show this help message and exit
  --print-number PRINT_NUMBER
                        an integer for printing repeatably
                        
 출처 : https://greeksharifa.github.io/references/2019/02/12/argparse-usage/

 

add_argument()
사용시 설정가능한 세부사항들


 Argument name

argument의 이름을 지정할 때 지정하는 방식에 따라서 keywording한 인자를 넘겨줄지 positional한 인자를 넘겨줄지가 달라진다. 인자의 이름앞에 -가 붙어있다면 keyword argument, 없다면 positional argument로 지정된다. 참고로 python에서 변수명에 -를 쓰지않는 것과는 다르게 -를 사용해도 된다.(물론 맨앞은 빼고!) 즉, --keyword-argument와 같은 방식으로 인자를 지정할 수 있다는 것이다. 물론 --positional_argument처럼 _를 사용할 수도 있다. 하지만, 두 argument모두 python runtime내에서는 keyword_arguement, positional_argument와 같은 형식으로 argument명이 변경된다.

parser.add_argument('--keyword-argument' )         # keyword
parser.add_argument('positional_argument')         # positional

args = parser.parse_args()
print('args.keyword_argument:', args.keyword_argument)
print('args.positional_argument:', args.positional_argument)

이 때 postional argument는 일반적으로 파이썬에서 함수의 positional argument를 다룰 때의 규칙과 어느정도 유사하다. 

  • positional argument가 여러개라면 순서를 반드시 지켜야한다.
  • positional argument는 반드시 값을 지정해줘야 한다.

반면, keyword argument는 이와 대비된다.

  • 값을 지정하지 않아도 되고, 이럴 경우 default값이 지정된다. 만약 default값을 지정해놓지 않았다면 None이 저장된다. 
  • keyword argument 뒤에는 반드시 저장할 값을 지정해야한다.
  • keyword argument에 값을 지정하는 방식은 2가지가 있다. '--keyword-argument 3' , '--keyword-argument=3'

추가적으로, arguement name을 한개가 아닌 여러개를 지정할 수도 있다.

parser.add_argument('--foo', '-f')

Type 지정

매우 중요한 부분이다. argparse에서 주어진 인자들을 parsing할 때 (즉, parse_args()가 실행될 때 ) 인자들을 모두 문자열 취급을 하게 된다. 따라서 int타입같은 다른 data type을 지정하고 싶다면, add_argument()에서 type옵션을 지정해줘야 한다. 해당 옵션의 default가 str인 것이다. type으로는 한개의 문자열에 대해서 return을 받을 수 있는 callable한 객체이다. 즉, str, int, float, bool 등인 것이다. 반면 list같은 것은 불가능하다. ( list의 경우 추후에 언급할 action에서 append값을 줌으로써 만들어낼 수 있다.)

parser.add_argument('--print-number', type=int)
> python argparseTest.py --print-number 5

Defulat값 지정

앞서 언급했듯 argument에 대해서 값을 터미널에서 지정하지 않았을 때 들어가는 default값을 설정해줄 수 있다. add_argument()의 default 옵션을 통해 지정해줄 수 있다.

parser.add_argument('--foo', type=int, default=5)

실제로 머신러닝 모델에서는 아래와 같이 사용된다.

import argparse

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--epoch', type=int, default=10)
    parser.add_argument('--data_root', type=str, default='D:\data\coco')
    parser.add_argument('--lr', type=float, default=1e-2)
    parser.add_argument('--batch_size', type=int, default=256)
    parser.add_argument('--momentum', type=float, default=0.9)
    parser.add_argument('--weight_decay', type=float, default=5e-4)
    opts = parser.parse_args()
    print(opts)

    batch_size = opts.batch_size
    print(batch_size)
    
    
출처 : https://csm-kr.tistory.com/19
~>python argparse_ex.py --epoch 20 --lr 1e-3
Namespace(batch_size=256, data_root='D:\\data\\coco', epoch=20, lr=0.001, momentum=0.9, weight_decay=0.0005)
20

출처 : https://csm-kr.tistory.com/19

 

추가적으로 인자의 action option과 이에 따른 dest 옵션을 지정해줄 수 있는데 이는 내가 지금 이 글을 작성하며 제일 많이 참고한 교수님의 글을 참고하기를 바란다.

 

References

https://wikidocs.net/13963

 

configparser 활용하기

### configparser는 왜필요한가? cfg, ini 파일 포맷을 활용하여 어플리케이션의 환경설정과 같은 데이터를 저장하고 불러올때 매우 유용하다. 이런 ...

wikidocs.net

https://docs.python.org/ko/3/library/configparser.html

 

configparser — 구성 파일 구문 분석기 — Python 3.10.2 문서

configparser — 구성 파일 구문 분석기 소스 코드: Lib/configparser.py 이 모듈은 마이크로소프트 윈도우 INI 파일과 유사한 구조를 제공하는 기본 구성 언어를 구현하는 ConfigParser 클래스를 제공합니다.

docs.python.org

https://greeksharifa.github.io/references/2019/02/12/argparse-usage/

 

Python, Machine & Deep Learning

Python, Machine Learning & Deep Learning

greeksharifa.github.io

https://csm-kr.tistory.com/19

 

python model config 하기 - configuration (argparse, ymal) 이용

안녕하세요~ pulluper 입니다. 오늘은 deep neural network 를 학습할 때, 그 구성을 변경하는데 많이 쓰이는 argparse 와 ymal 에 대하여 알아보겠습니다. 😊 대규모 혹은 논문을 위한 실험은 여러가지의 구

csm-kr.tistory.com

 

'Python' 카테고리의 다른 글

[Typing] Literal, tensortype ( torch typing )  (0) 2023.03.18
Python - JSON & Pickle  (0) 2022.02.17
Python - Exception Handling  (0) 2022.02.16
Python - File Handling & With Statement  (0) 2022.02.16
Python - Module & Project  (0) 2022.02.15