Pylint

About_work·2022년 12월 28일
1

python clean code

목록 보기
2/11

Pylint 기초

  • 역할
    • 특정 유형의 에러 찾기
    • 코드 일부분에 대한 리펙토링을 제공
    • 코드 복잡성에 대한 자세한 정보 제공
    • PEP8 표준 적용
    • 여러 메시지를 표시 가능
    • 다른 파일에서 발견되는 경고 및 에러 수에 대한 통계치를 표시하는데 사용
      • 메시지는 에러/경고와 같은 다양한 카테고리로 분류됩니다.
      • 경고 및 오류의 수와 심각도에 따라 코드에 전체적인 표시가 붙는다.
  • 그 외 정보
    • 유사한 툴로, pyflakes / flake8 / mypy 등이 있습니다.
  • 설치
>>> pip install pylint

>>> pylint --long-help
  • 파이참에서 Pylint 플러그인으로 추가

    • 파이참을 실행하여 나오는 메뉴 중, [FIle]->[Settings] 메뉴를 선택하여 줍니다.
    • 아래와 같이 따라합니다.
    • 파이참 재실행 후, 아래와 같이 실행해줍니다.
  • Output

    • MESSAGE_TYPE: LINE_NUM:[OBJECT:] MESSAGE
      • MESSAGE_TYPE
        • (C) convention, 프로그래밍 표준 위반
        • (R) refactor, 나쁜 코드의 냄새가 난다..
        • (W) warning, python specific 문제
        • (E) error, 가능성 있는 버그
        • (F) fatal, pylint가 추가 처리를 수행하지 못하게 하는 오류가 발생한 경우
  • Output status code

    • 0 : 다 좋다!
    • 1: fatal 이 있는 경우
    • 2: error 가 있는 경우
    • 4: warning 이 있는 경우
    • 8: refactor가 있는 경우
    • 16: convention이 있는 경우
    • 32: usage error이 있는 경우
  • 사용 팁

    • 너무 장황한 코멘트를 주면, 아래의 옵션을 주어 조용히 시킬 수 있다.
      • pylint가 코드를 분석할 때, 활성화할 메세지 카테고리를 이용할지 안할지 정한다.
        • 코드에 코드에 # pylint: disable=C0304 와 같이 추가하면 필요없는 경고는 끌 수 있습니다.
        • report 통계 끄기
          • pylint -reports=n 파일명.py
          • -rn으로 줄여 쓸 수 있다.
        • 행당 길이 조절
          • pylint --max-line-length=79 파일명.py
      • 사용자 지정 configuration file 만들기
        • 설정 파일 만들기: 파일경로/pylint -rn --max-line-length=79 --generate-rcfile > 설정파일명.pylintrc
        • 설정 파일 사용하기
          • pylint --rcfile 설정파일명.pylintrc 파일명

예시

  • lint.py 라는 파일을 검사해 봅시다.
import string

shift = 3
choice = input("would you like to encode or decode?")
word = input("Please enter text")
letters = string.ascii_letters + string.punctuation + string.digits
encoded = ''
if choice == "encode":
    for letter in word:
        if letter == ' ':
            encoded = encoded + ' '
        else:
            x = letters.index(letter) + shift
            encoded=encoded + letters[x]
if choice == "decode":
    for letter in word:
        if letter == ' ':
              encoded = encoded + ' '
        else:
            x = letters.index(letter) - shift
            encoded = encoded + letters[x]
            
print(encoded)
  • 아래와 같이 커멘트 창에서 실행해보자!
pylint lint.py

************* Module lint
lint.py:14:19: C0326: Exactly one space required around assignment
            encoded=encoded + letters[x]
                   ^ (bad-whitespace)
lint.py:24:0: C0304: Final newline missing (missing-final-newline)
lint.py:1:0: C0111: Missing module docstring (missing-docstring)
lint.py:3:0: C0103: Constant name "shift" doesn't conform to UPPER_CASE naming style (invalid-name)
lint.py:4:0: C0103: Constant name "choice" doesn't conform to UPPER_CASE naming style (invalid-name)
lint.py:5:0: C0103: Constant name "word" doesn't conform to UPPER_CASE naming style (invalid-name)
lint.py:6:0: C0103: Constant name "letters" doesn't conform to UPPER_CASE naming style (invalid-name)
lint.py:7:0: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
-------------------------------------------------------------------
Your code has been rated at 4.74/10 (previous run: -0.53/10, +5.26)

Pylintrc ?


lint 분석 결과 보는 법

Trailing whitespace

  • 줄의 끝과 새 줄 사이에 whitespace가 있을 때

relative-beyond-top-level / W0621

  • Message emitted:
  • Description:
    • 상대 import가 현재 package로부터 너무 많은 level에 접근하려고 할 때

redefined-outer-name / W0621

  • Message emitted:
    Redefining name %r from outer scope (line %s)

  • Description:
    변수 이름이 "외부 범위 혹은 except handler 에 정의된 이름"을 숨기는 경우 사용

consider-iterating-dictionary / C0201

  • Message emitted:
    Consider iterating the dictionary directly instead of calling .keys()
  • Description:
    • dictionary의 keys가 .keys() 메서드를 통해 iterated 될 때, 혹은 .keys() 가 membership check로 쓰일 때.
    • dictionary 그 자체를 통해 iterate 하는 것으로 충분하다. ( for key in dictionary.)
    • membership check의 경우에는 if key in dictionary 가 더 빠르다.
  • 잘못된 코드
FRUITS = {"apple": 1, "pear": 5, "peach": 10}


for fruit in FRUITS.keys():  # [consider-iterating-dictionary]
    print(fruit)
  • 잘된 코드
FRUITS = {"apple": 1, "pear": 5, "peach": 10}

for fruit in FRUITS:
    print(fruit)

wildcard-import / W0401

  • Message emitted:
    Wildcard import %s
  • Description:
    • Used when from module import * is detected.
  • 잘못된 코드
from abc import *  # [wildcard-import]
  • 잘된 코드
# Either import module or
# only import required objects from module.
import abc
from abc import ABC, abstractmethod

modified-iterating-dict / E4702

  • Message emitted:
Iterated dict '%s' is being modified inside for loop body, iterate through a copy of it instead.
  • Description:
    • 반복되고 있는 dictionary가 더해지거나 제거될 때 발생한다. 이것은 RuntimeError을 일으킬 수 있다.
  • 잘못된 코드
fruits = {"apple": 1, "orange": 2, "mango": 3}

i = 0
for fruit in fruits:
    fruits["apple"] = i  # [modified-iterating-dict]
    i += 1
  • 잘된 코드
fruits = {"apple": 1, "orange": 2, "mango": 3}

i = 0
for fruit in fruits.copy():
    fruits["apple"] = i
    i += 1
profile
새로운 것이 들어오면 이미 있는 것과 충돌을 시도하라.

2개의 댓글

comment-user-thumbnail
2023년 1월 10일

항상 감사합니다

1개의 답글