Programming/Python

[Python/VSCode] 독스트링 스타일과 autoDocstring

Jonghyuk Baek 2022. 3. 7. 23:07

Introduction

예전 포스트에서는 파이썬의 독스트링에 대해 간략히 소개를 했었다. 링크 

 

독스트링은 파이썬 스크립트 내부에 함수, 클래스, 모듈에 대한 정보를 적어놓은 문자열로 그 자체로 코드 도큐멘테이션의 기능을 한다. 독스트링이 꼼꼼하게 적혀있을수록 작성자 이외의 다른 사용자가 코드의 목적작동 방식을 파악하기가 쉬워지며, 최종적으로는 이런 독스트링들을 모아 하나의 라이브러리 문서를 구성하는 것도 가능하다.

 

이전 글 말미에서는 정형화된 문서화 컨벤션을 따라 독스트링을 작성해 놓으면 문서화 툴을 이용한 라이브러리 도큐멘테이션이 가능하다고 언급했는데 이번 포스트에서는 어떤 독스트링 스타일 컨벤션 들이 있는지 알아보고, 일관된 스타일의 독스트링을 작성하는 데 도움이 되는 툴을 소개할 것이다.


Docstring Styles

Python Enhancement Proposal 중 하나인 PEP 257 에서 기본적인 독스트링 작성 가이드를 제시해 주고는 있다. 하지만 그렇게까지 extensive한 룰을 강제하고 있지는 않아, 이 가이드만을 따른다 했을 때 독스트링의 규칙성/가독성이 그렇게 좋은 편은 아니다.

 

더 나은 규칙성과 가독성을 위해 흔히 사용되는 독스트링 스타일들이 따로 존재하는데, 대표적인 것들로는 아래가 있다.

  • Google-Style
  • Numpy-Style
  • Sphnix-Style (Restructured Text - RST)

Google-Style

def abc(a: int, c = [1,2]):
    """_summary_

    Args:
        a (int): _description_
        c (list, optional): _description_. Defaults to [1,2].

    Raises:
        AssertionError: _description_

    Returns:
        _type_: _description_
    """
    if a > 10:
        raise AssertionError("a is more than 10")

    return c

구글이 제공하는 파이썬 스타일 가이드 (Google Python Style Guide) 에서 제시된 독스트링 스타일이다.

 

아마 가장 많이 보아온 형태일텐데, 위와 코드를 보면 간략한 첫 줄 소개, 세부 설명을 하는 다음 단락 (코드에선 생략됨), 그리고 Args / Raises / Returns 로 함수 독스트링을 구성하고 있다. 클래스의 경우 클래스 소개와 함께 Attributes 항목이 대신 들어간다. 위 코드에서는 대략 어떤 양식으로 해당 내용들이 들어가고 있는 지만 보면 좋을 듯 하다.

Numpy-Style

def abc(a: int, c = [1,2]):
    """_summary_

    Parameters
    ----------
    a : int
        _description_
    c : list, optional
        _description_, by default [1,2]

    Returns
    -------
    _type_
        _description_

    Raises
    ------
    AssertionError
        _description_
    """
    if a > 10:
        raise AssertionError("a is more than 10")

    return c

Numpy Style Guide에서 제공하는 독스트링 양식이다. 예시를 보면 Short summary, Parameters, Returns, Raises 의 구성으로 구글 스타일과 양식이 조금 다르고 내용물은 크게 다르지 않다. 필요하다면 Deprecation warning 에 대한 내용이나 알고리즘에 대한 discussion을 작성하는 Notes 섹션을 추가할 수 있으며, 이에 대한 양식도 따로 정해져 있다.

 

사족으로, 실제로 Numpy 라이브러리에 정의된 독스트링을 불러와 보면 Numpy-Style로 적힌 것을 확인할 수 있다. 아래는 np.ndarray에 대한 독스트링이다.

>>> import numpy
>>> print(numpy.ndarray.__doc__)
ndarray(shape, dtype=float, buffer=None, offset=0,
            strides=None, order=None)

    An array object represents a multidimensional, homogeneous array
    of fixed-size items.  An associated data-type object describes the
    format of each element in the array (its byte-order, how many bytes it
    occupies in memory, whether it is an integer, a floating point number,
    or something else, etc.)

    Arrays should be constructed using `array`, `zeros` or `empty` (refer
    to the See Also section below).  The parameters given here refer to
    a low-level method (`ndarray(...)`) for instantiating an array.

    For more information, refer to the `numpy` module and examine the
    methods and attributes of an array.

    Parameters
    ----------
    (for the __new__ method; see Notes below)

    shape : tuple of ints
        Shape of created array.
    dtype : data-type, optional
        Any object that can be interpreted as a numpy data type.
    buffer : object exposing buffer interface, optional
        Used to fill the array with data.
    offset : int, optional
        Offset of array data in buffer.
    strides : tuple of ints, optional
        Strides of data in memory.
    order : {'C', 'F'}, optional
        Row-major (C-style) or column-major (Fortran-style) order.

    Attributes
    ----------
    T : ndarray
        Transpose of the array.
...

Sphnix-Style

def abc(a: int, c = [1,2]):
    """_summary_

    :param a: _description_
    :type a: int
    :param c: _description_, defaults to [1,2]
    :type c: list, optional
    :raises AssertionError: _description_
    :return: _description_
    :rtype: _type_
    """
    if a > 10:
        raise AssertionError("a is more than 10")

    return c

스핑크스 스타일은 reStructuredText 라는, 파이썬 기술 문서화를 위해 주로 이용되는 마크업 언어를 이용해 독스트링을 작성한다. 마크업 언어 치고 raw contents를 읽어도 내용을 직관적으로 이해하기 쉬우며 문법이 간단하다는 장점이 있지만...... 독스트링으로써 읽기에는 아무래도 너무 컴팩트하고 규칙이 생소한 감이 있다. 그 자체로 문서화가 가능해 특별한 변환이 없어도 문서를 생성할 수 있지만.. 개인적으로는 그렇게 추천하고 싶지는 않다.

 

.

.

.

 

이렇게 여러 가지의 독스트링 작성 스타일이 존재하는데, 항상 정형화된 독스트링을 작성할 수 있도록 독스트링의 스타일을 완전히 외우고 다녀야 하는 걸까? 스핑크스나 pdoc과 같은 문서화 툴에서 기대하는 포맷에 어긋나게 작성할 경우 문서화 과정에서 의도와 다르게 내용이 처리될 수 있다.

 

사실 더 정형화되어 문서화가 쉬운 독스트링 형식이라는 것은, 프로그램이 룰 베이스로 알아서 생성해 내기에도 쉽다는 뜻으로도 볼 수 있다. 그리고 실제로도 더욱 편하게 독스트링을 작성할 수 있도록 도와주거나, 독스트링 스타일 체크를 해 주는 툴들도 많이 있다.

 

이번에는 이미 작성된 코드 내용을 기반으로 독스트링을 어느 정도 완성시켜 주는 autoDocstring 이라는 VSCode extension에 대해 간략히 소개하고 마치겠다.

 

autoDocstring - Python Docstring Generator

별이 다섯개 만땅이다

autoDocstring은 VSCode 확장 프로그램 중 하나로, 파이썬 함수에 대해서 빠르게 독스트링을 생성해 준다. 여러 가지의 독스트링 포맷을 지원하고 있으며, 원하는 스타일로 독스트링을 생성하도록 설정해 줄 수 있다. 만약 코드 자체에 독스트링 작성에 참고가 될 만한 정보 (타입 힌트, 인자 목록, 디폴트 값, raise 정보) 가 있다면 이를 알아서 독스트링에 반영해 준다.

Examples

한번 예시를 보자. 아래와 같이 간단히 코드를 작성해 놓았다고 할 때,

# Sample code
class NumpyIntegerContainer:
    def __init__(self, var_a: int, var_b: Optional[int] = None):
        self.a = var_a
        self.b = var_b

    def return_ab_tuple(self) -> Tuple:
        return self.a, self.b

autoDocstring이 작성해 준 구글 스타일 독스트링은 아래와 같다.

# Google-Style
class NumpyIntegerContainer:
    """_summary_
    """
    def __init__(self, var_a: int, var_b: Optional[int] = None):
        """_summary_

        Args:
            var_a (int): _description_
            var_b (Optional[int], optional): _description_. Defaults to None.
        """
        self.a = var_a
        self.b = var_b

    def return_ab_tuple(self) -> Tuple:
        """_summary_

        Returns:
            Tuple: _description_
        """
        return self.a, self.b

함수 인자와 반환 값 정보를 읽어 이들을 반영한 독스트링을 만들어 준다. 언더바로 묶여 있는 부분들만 사용자가 직접 채워넣어 주면 된다.

 

만약 함수에서 raise 하는 에러가 따로 있다면, 아래와 같이 이런 정보들 또한 독스트링에 포함시켜 준다.

# Google-Style
def add_one_to_integer(x: int = 0) -> int:
    """_summary_

    Args:
        x (int, optional): _description_. Defaults to 0.

    Raises:
        TypeError: _description_

    Returns:
        int: _description_
    """
    if not isinstance(x, int):
        raise TypeError("Wrong input type.")
    x = x + 1
    return x

 

같은 코드에 대해 Numpy Style로 생성하면 아래와 같이 나온다.

# Numpy-Style
class NumpyIntegerContainer:
    """_summary_
    """
    def __init__(self, var_a: int, var_b: Optional[int] = None):
        """_summary_

        Parameters
        ----------
        var_a : int
            _description_
        var_b : Optional[int], optional
            _description_, by default None
        """
        self.a = var_a
        self.b = var_b

    def return_ab_tuple(self) -> Tuple:
        """_summary_

        Returns
        -------
        Tuple
            _description_
        """
        return self.a, self.b

특히 Numpy 스타일의 경우 여러 개의 대시로 이루어진 라인이 들어가 유난히 손으로 적기가 어려운데, 자동으로 큰 틀을 생성해 주니 굉장히 편리하다.

Usage

이 extension에서는 현재

  • Google
  • Numpy
  • Sphnix
  • docBlockr
  • one-line-sphnix
  • PEP257

의 독스트링 스타일을 지원하며, PEP257은 비교적 최근에 추가되었다. 이 스타일은 PEP 257에 제시된 독스트링 example을 기반으로 비슷하게 작성해 주는 것으로 추정된다.

 

Extension을 enable 해 두면 단순히 """ 이후 엔터를 치는 것으로 바로 해당 커서 지점에서 독스트링을 자동 생성할 수 있으며, ctrl+shift+2 버튼이나 vscode의 커맨드로도 실행할 수 있다.

 

굉장히 사용법이 쉽고 사전 작업도 그리 많지 않지만, 다만 현재 코드에 적힌 내용을 기반으로 독스트링을 만들어 주기 때문에 타입 힌트 등을 미리미리 적어놓지 않을 수록 생성된 독스트링도 영양가가 부실해진다는 점이 걸릴 수 있다.

# 든든한 독스트링
def add_one_to_real(x: Union[int, float] = 0) -> Union[int, float]:
    """_summary_

    Args:
        x (Union[int, float], optional): _description_. Defaults to 0.

    Returns:
        Union[int, float]: _description_
    """
    x = x + 1
    return x

# 빈약한 독스트링
def add_one_to_real(x):
    """_summary_

    Args:
        x (_type_): _description_

    Returns:
        _type_: _description_
    """
    x = x + 1
    return x

그런데 일반적으로는 타입 힌트와 독스트링의 타입 어노테이션은 굳이 중복해 쓰지 않기 때문에, 이런 데서 살짝 딜레마가 온다.

 

하지만 그렇다 해도 완벽하게 포맷팅 된 독스트링을 내용 기반으로 자동 생성해 준다는 점은 포기할 수 없는 이점으로 보인다. 형식에 맞춘 기나긴 독스트링 작성에서 데서 오는 피로감, 거부감을 줄이면서 더 많은 양의 informative한 독스트링을 작성할 수 있게 되고, 이를 통해 프로젝트의 문서화 기반을 다질 수 있을 것이다.

 

이것 이외에 디스크립션 까지도 알아서 작성해 주는 AI 기반의 파이썬 독스트링 생성기도 존재하는데, 추후에 다뤄보도록 하겠다.


아래는 참고할 만한 사이트이다.

References

[Python] 독스트링 (Docstrings)

https://jh-bk.tistory.com/15

PEP 257 -- Docstring Conventions

https://www.python.org/dev/peps/pep-0257/

Sphnix Documentation

https://www.sphinx-doc.org/en/master/

autoDocstring: VSCode Python Docstring Generator (스타일 샘플을 여기서 참조했다)

https://github.com/NilsJPWerner/autoDocstring

Google Python Style Guide

https://google.github.io/styleguide/pyguide.html

Numpy Style Guide

https://numpydoc.readthedocs.io/en/latest/format.html

reStructuredText (RST) 위키피디아 페이지

https://en.wikipedia.org/wiki/ReStructuredText

반응형