본문 바로가기

Programming

Black을 이용한 코드 스타일 맞추기

728x90
반응형

분석가들의 python 코드 스타일은 정말 제각각이다. linting이나 코드 스타일을 맞추는 것에 신경 쓰고 있지 않았는데 제품에 올리고 협업을 하며 코드 스타 일을 맞추는 것의 필요성을 느꼈다. 오늘은 코드 스타일을 자동으로 포매팅해주는 Black을 알아보고자 한다.


https://github.com/psf/black

 

GitHub - psf/black: The uncompromising Python code formatter

The uncompromising Python code formatter. Contribute to psf/black development by creating an account on GitHub.

github.com

 

Black은 "The Uncompromising Code Formatter", 즉 타협하지 않는 코드 포매터를 표방하며 사용자가 직접 교정하고 고민하는 시간을 줄여주는데 집중한다. 코드 스타일은 PEP8을 따른다.

코드 내에서 black의 포매팅을 원하지 않는 부분은 주석으로 # fmt: skip# fmt: off처리를 해서 건너뛸 수 있다. 해당 부분이 끝나면 # fmt: on으로 적용받도록 한다.


설치

pip install black

사용

콘솔에 입력한다. 단일 파일이나 특정 디렉토리 내의 전체 파일에 적용할 수 있다.

black {source_file_or_directory}

옵션

많이 사용하는 것은 다음과 같다.

-l : 한 라인 최대 글자 수
—diff : 파일을 변경하지 않고 변경되는 부분을 콘솔로 보여줌
—color : —diff 사용 시 변경점에 색 적용

더 자세한 옵션은 아래 페이지에서 확인할 수 있다.

The basics - Black 22.6.0 documentation

 

The basics - Black 22.6.1.dev4 documentation

Previous Usage and Configuration

black.readthedocs.io

 

예제

case1

변경 전

import pandas as pd

def get_basic_summary_feats(data:pd.DataFrame, groupby_col_name:str,
                            agg_list: list=['mean', 'std', 'min', 'max', 'median', 'skew', 'last', 'first']) -> pd.DataFrame:
    """
    연속형 변수에 aggregation 기본 제공 항목에 대한 groupby 진행.
    :param data: groupby 진행할 dataframe
    :param groupby_col_name: groupby 기준 컬럼 명
    :param agg_list: pandas aggregation에서 기본적으로 제공하는 함수명의 list
    :return:
    """
    result = data.groupby(groupby_col_name).agg(agg_list)
    result.columns = ['_'.join(x) for x in result.columns]
    result = result.reset_index()
    return result

 

실행

black features/numeric_summary.py

 

변경 후 : 함수 인자 선언 부분과 ' 이 바뀌었음을 알 수 있다.

import pandas as pd

def get_basic_summary_feats(
    data: pd.DataFrame,
    groupby_col_name: str,
    agg_list: list = ["mean", "std", "min", "max", "median", "skew", "last", "first"],
) -> pd.DataFrame:
    """
    연속형 변수에 aggregation 기본 제공 항목에 대한 groupby 진행.
    :param data: groupby 진행할 dataframe
    :param groupby_col_name: groupby 기준 컬럼 명
    :param agg_list: pandas aggregation에서 기본적으로 제공하는 함수명의 list
    :return:
    """
    result = data.groupby(groupby_col_name).agg(agg_list)
    result.columns = ["_".join(x) for x in result.columns]
    result = result.reset_index()
    return result

 

Case2

변경 전

import pandas as pd
import numpy as np
from datetime import datetime
from dateutil.relativedelta import relativedelta


def period(x: np.array) -> np.array:
    return x.max() - x.min()


def get_month_index(df: pd.DataFrame, date_col_name: str) -> pd.DataFrame:
    """
    datetime 컬럼에서 month 기준, 시간 순서대로 int로 변환 (첫달 -> 0)
    :param df:
    :param date_col_name: datetime 컬럼명
    :return:
    """
    start_month = datetime.strftime(df[date_col_name].min(), '%Y-%m')
    end_month = datetime.strftime(df[date_col_name].max() + relativedelta(months=1), '%Y-%m')
    time_range = pd.date_range(start_month, end_month, freq='M', inclusive='right')
    time_dict = {datetime(k.year, k.month, 1): v for k, v in zip(time_range, range(0, len(time_range)))}
    df['paymonth_idx'] = df[date_col_name].apply(lambda x: time_dict[datetime(x.year, x.month, 1)])
    df = df.drop(date_col_name, axis=1)
    return df


def period(x: np.array) -> np.array:
        return x.max() - x.min()


def get_payment_basic_feats(df: pd.DataFrame, date_col_name: str, groupby_col_name: str) -> pd.DataFrame:
    """
    :param df: groupby 진행할 dataframe
    :param date_col_name: datetime 컬럼 명
    :param groupby_col_name: groupby 기준 컬럼 명
    :return: groupby 결과
    """
    df = df.loc[:, [groupby_col_name, date_col_name]]
    # change payment month to int
    df = get_month_index(df, date_col_name)

    # agg: first, last, period
    result = df.groupby(groupby_col_name).agg(['first', 'last', period])
    result.columns = ['_'.join(x) for x in result.columns]
    result = result.reset_index()

    return result



if __name__ == '__main__':
    data = pd.read_feather('./SH/data/train_data.ftr')
    train_payment_feats = get_payment_basic_feats(data, date_col_name='S_2', groupby_col_name='customer_ID')

 

실행 : --diff 옵션 적용

black features/paydate_basic.py --diff

 

변경 후 : 코드가 바뀌지 않고 변경된 코드가 콘솔에 출력

 

Case3

실행 : case 2에 --color 옵션 추가

black features/paydate_basic.py --diff --color

 

변경 후

728x90
반응형

'Programming' 카테고리의 다른 글

파이썬 로그 핸들링  (0) 2022.08.01
파이썬 예외처리  (0) 2022.08.01
[Library] Dask 추가 정보 및 테스트  (0) 2022.07.10
[Library] Dask? Spark?  (0) 2022.07.05
정규표현식 / 파이썬 예제 (re)  (0) 2022.06.27