ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Python] Pylint - 정의와 예제를 통해 Python 린트 툴 알아보기
    Software Development/Python 2020. 9. 3. 19:00

    Lint?

    린트(lint) 또는 린터(linter)는 소스 코드를 분석하여 프로그램 오류, 버그, 스타일 오류, 의심스러운 구조체에 표시(flag)를 달아놓기 위한 도구들을 말합니다. 이 용어는 C 언어 소스 코드를 검사하는 유닉스 유틸리티에서 왔습니다.

     

    Pylint란

    Pylint는 Python 코드의 에러를 확인하고, 표준을 적용시키며 코드의 이상한 부분을 찾는 도구입니다. 또한 특정 유형의 에러를 찾을 수 있으며, 코드 일부분에 대한 리팩토링을 제공하며 코드의 복잡성에 대한 자세한 정보를 제공하기도 합니다. 

     

    Python에서 다른 종류의 유사한 툴로 pychecker, pyflakes, flake8, mypy 등이 있습니다. Pylint에서 사용하는 기본적인 코딩 스타일은 PEP8이라 보시면 됩니다.

     

    Pylint는 코드를 분석할 때 여러 메세지를 표시하고 다른 파일에서 발견되는 경고 및 에러 수에 대한 통계치를 표시하는데 사용할 수도 있습니다. 메세지는 에러 경고와 같은 다양한 카테고리로 분류됩니다. 경고 및 오류의 수와 심각도에 따라 코드에 전체적인 표시가 붙습니다.

     

    그러나 Pylint가 제시하는 것이 절대적인 것은 아닙니다. Pylint는 오류에 대해 최소한으로 알려주려고 하지만 너무 장황하게 경고를 줄 수 있습니다. Pylint가 좋은 코드에 대해서도 언급이 있을 수 있으니 사용자가 유의해서 메시지를 참고하면 됩니다.

     

    Pylint가 너무 장황한 헛소리를 하면 아래의 옵션을 주어 조용히 시킬 수 있습니다.

     

    * Pylint가 코드를 분석할 때 활성화할 메세지 카테고리를 이용할지 안할지 정한다.

    * 사용자 지정 configuration file 만들기

    나중에 위 두 방식 모두 예제를 통해 알아 보도록 하겠습니다.

     

    Pylint를 사용하면 PEP8을 따르기 때문에 다른 사람들이 봐도 쉽게 코드를 이해할 수 있고 그렇기 때문에 더 많은 사름드에게 사랑받는 코드가 됩니다. 

     

    Pylint 예제

     

    Pylint를 설치하기 위해 커맨드 창에서 아래와 같이 실행하면 Pylint를 설치하실 수 있습니다.

    pip install pylipy

    pip install pylint

    pip install pylint

     

    커맨드 창에 Pylint를 입력하시면 help dialogue가 호출됩니다.

      pylint --long-help
      ...
      Output:
        Using the default text output, the message format is :
        MESSAGE_TYPE: LINE_NUM:[OBJECT:] MESSAGE
        There are 5 kind of message types :
        * (C) convention, for programming standard violation
        * (R) refactor, for bad code smell
        * (W) warning, for python specific problems
        * (E) error, for probable bugs in the code
        * (F) fatal, if an error occurred which prevented pylint from doing
        further processing.
    
      Output status code:
        Pylint should leave with following status code:
        * 0 if everything went fine
        * 1 if a fatal message was issued
        * 2 if an error message was issued
        * 4 if a warning message was issued
        * 8 if a refactor message was issued
        * 16 if a convention message was issued
        * 32 on usage error
        status 1 to 16 will be bit-ORed so you can know which different
        categories has been issued by analysing pylint output status code
    ...
    

     

    아래의 코드는 Pylint에 실행시킬 파이썬 코드입니다. 

    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
    
    lint.py:9:0: W0311: Bad indentation. Found 2 spaces, expected 4 (bad-indentation)
    lint.py:10:0: W0311: Bad indentation. Found 6 spaces, expected 8 (bad-indentation)
    lint.py:11:0: W0311: Bad indentation. Found 10 spaces, expected 12 (bad-indentation)
    lint.py:12:0: W0311: Bad indentation. Found 6 spaces, expected 8 (bad-indentation)
    lint.py:13:0: W0311: Bad indentation. Found 10 spaces, expected 12 (bad-indentation)
    lint.py:14:0: W0311: Bad indentation. Found 10 spaces, expected 12 (bad-indentation)
    lint.py:14:17: C0326: Exactly one space required around assignment
              encoded=encoded + letters[x]
                     ^ (bad-whitespace)
    lint.py:16:0: W0311: Bad indentation. Found 2 spaces, expected 4 (bad-indentation)
    lint.py:17:0: W0311: Bad indentation. Found 6 spaces, expected 8 (bad-indentation)
    lint.py:18:0: W0311: Bad indentation. Found 10 spaces, expected 12 (bad-indentation)
    lint.py:19:0: W0311: Bad indentation. Found 6 spaces, expected 8 (bad-indentation)
    lint.py:20:0: W0311: Bad indentation. Found 10 spaces, expected 12 (bad-indentation)
    lint.py:21:0: W0311: Bad indentation. Found 10 spaces, expected 12 (bad-indentation)
    lint.py:23: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 -0.53/10

    실행 결과를 보면 라인별로 어떤 문제가 있는지를 설명해주며 점수를 매겨 줍니다.

    들여쓰기를 수정해서 다시 실행 해보겠습니다.

     

     

    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)
    ************* 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)

    들여쓰기를 수정해서 다시 실행해보니 -0.53에서 4.74로 점수가 올랐습니다.

     

    line 14의 띄어쓰기 부분을 추가하겠습니다. 

    Your code has been rated at 6.32/10 (previous run: 5.79/10, +0.53)

     

     

     

    모듈의 docstring을 추가하여 또 점수를 올려봅시다.

    import string
    """This script prompts a user to enter a message to encode or decode
    using a classic Caesar shift substitution (3 letter shift)"""
    
    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)
    Your code has been rated at 6.84/10 (previous run: 6.84/10, +0.00)
    lint.py:27:0: C0304: Final newline missing (missing-final-newline)
    lint.py:6:0: C0103: Constant name "shift" doesn't conform to UPPER_CASE naming style (invalid-name)
    lint.py:7:0: C0103: Constant name "choice" doesn't conform to UPPER_CASE naming style (invalid-name)
    lint.py:8:0: C0103: Constant name "word" doesn't conform to UPPER_CASE naming style (invalid-name)
    lint.py:9:0: C0103: Constant name "letters" doesn't conform to UPPER_CASE naming style (invalid-name)
    lint.py:10:0: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)

    점수가 6.84로 올랐습니다. 그러나 invalid-name이 뜹니다.

    이건 어떻게 해야할까요?

    상수는 대문자로 하는 것이 관례입니다. 변수명을 대문자로 수정 후 다시 돌려보겠습니다.

     

    """This script prompts a user to enter a message to encode or decode
    using a classic Caesar shift substitution (3 letter shift)"""
    
    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)
    ************* Module lint
    lint.py:27:0: C0304: Final newline missing (missing-final-newline)
    
    ------------------------------------------------------------------
    Your code has been rated at 10.00/10 (previous run: 9.47/10, +2.63)

    이제 점수가 거의 10점이 나왔습니다. 

     

    코드에 문제가 없어 보이는데 마지막 라인을 추가하지 않아서 에러가 나고 있습니다. 라인을 추가하여 에러를 없앨 수 있지만

    필요에 의해 C0304을 꺼버리고 싶다면 아래와 같이 할 수 있습니다.

    print(ENCODED) # pylint: disable=C0321
    
    Your code has been rated at 10.00/10 (previous run: 9.47/10, +0.53)

    이제 10점이 나왔습니다. 코드에 # pylint: disable=C0304와 같이 추가하면 필요없는 경고는 끌 수 있습니다. 

     

    [1] ko.wikipedia.org/wiki/%EB%A6%B0%ED%8A%B8_(%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4)

    [2] pylint.pycqa.org/en/latest/intro.html

    [3] pypi.org/project/pylint/

     

    댓글

Designed by Tistory.