当前位置: 首页 > 工具软件 > Pylint > 使用案例 >

Python 代码检查工具 pylint (快速上手)

邹禄
2023-12-01

安装和配置

1. 安装

> pip install pylint

若下载遇到问题,可以参考此篇文章,更改软件源。

2. 检查是否安装

> pylint --version
pylint 2.8.3
astroid 2.5.6
Python 3.7.9

3. 生成默认配置文件

>pylint --persistent=n --generate-rcfile > pylint.conf
No config file found, using default configuration

会在当前目录下,生成 pylint.conf 文件,该文件中的配置项都是 pylint 的默认配置。

4. 查看帮助文件

> pylint --help
> pylint --long-help (查看更多帮助)

快速上手

使用 simplecaesar.py python 脚本作为测试文件

 1  #!/usr/bin/env python3
 2
 3  import string;
 4
 5  shift = 3
 6  choice = input("would you like to encode or decode?")
 7  word = input("Please enter text")
 8  letters = string.ascii_letters + string.punctuation + string.digits
 9  encoded = ''
10  if choice == "encode":
11      for letter in word:
12          if letter == ' ':
13              encoded = encoded + ' '
14          else:
15              x = letters.index(letter) + shift
16              encoded = encoded + letters[x]
17  if choice == "decode":
18      for letter in word:
19          if letter == ' ':
20              encoded = encoded + ' '
21          else:
22              x = letters.index(letter) - shift
23              encoded = encoded + letters[x]
24
25  print(encoded)

1. 测试单个文件

>pylint --rcfile=pylint.conf simplecaesar.py

************* Module simplecaesar
C:  1, 0: Missing module docstring (missing-docstring)
W: 14,12: Unused import django (unused-import)

每次命令添加 --rcfile 选项会比较繁琐,重命名pylint.conf.pylintrc,即不需要每次执行都带上--rcfile参数了。

2. 测试整个工程

> pylint package_name(package_name为包名称,根目录下需添加init.py)

3. 生成报告样例

> pylint simplecaesar.py
************* Module simplecaesar
simplecaesar.py【模块名称】:3:0:【行号:列号】 W0301【W 代表检查级别, 303 为编号】: Unnecessary semicolon【详细消息】 (unnecessary-semicolon)【问题消息ID号, <msg-id>】
simplecaesar.py:1:0: C0114: Missing module docstring (missing-module-docstring)
simplecaesar.py:5:0: C0103: Constant name "shift" doesn't conform to UPPER_CASE naming style (invalid-name)
simplecaesar.py:9:0: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
simplecaesar.py:13:12: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)

-----------------------------------
Your code has been rated at 7.37/10

所有告警类别

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.[致命错误]

可以通过 pylint --help-msg <msg-id> 获取更多告警帮助信息

>pylint --help-msg trailing-whitespace
:trailing-whitespace (C0303): *Trailing whitespace*
  Used when there is whitespace between the end of a line and the newline. This
  message belongs to the format checker.

4. 根据意见修改

根据意见,在第二行增加文档字符串,去除第三行;

 1  #!/usr/bin/env python3
 2  """This script prompts a user to enter a message to encode or decode
 3  using a classic Caesar shift substitution (3 letter shift)"""
 4
 5  import string
 6
 7  shift = 3
 8  choice = input("would you like to encode or decode?")
 9  word = input("Please enter text")
10  letters = string.ascii_letters + string.punctuation + string.digits
11  encoded = ''
12  if choice == "encode":
13      for letter in word:
14          if letter == ' ':
15              encoded = encoded + ' '
16          else:
17              x = letters.index(letter) + shift
18              encoded = encoded + letters[x]
19  if choice == "decode":
20      for letter in word:
21          if letter == ' ':
22              encoded = encoded + ' '
23          else:
24              x = letters.index(letter) - shift
25              encoded = encoded + letters[x]
26
27  print(encoded)
robertk01 Desktop$ pylint simplecaesar.py
************* Module simplecaesar
simplecaesar.py:7:0: C0103: Constant name "shift" doesn't conform to UPPER_CASE naming style (invalid-name)
simplecaesar.py:11:0: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
simplecaesar.py:15:12: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)

------------------------------------------------------------------
Your code has been rated at 8.42/10 (previous run: 7.37/10, +1.05)

比起上一版程序,评分提高 1.05,只剩下 invalid-name 信息。

这是因为 Pylint 中遵从 PEP 8 对象命名规范,使用大写,小写以及分隔符来定义变量、函数和类名,Pylint 通过正则表达式验证, (([A-Z_][A-Z1-9_]*)|(__.*__))$。例子中,常数变量应该采用全大写,这和 Pylint 缺省的规范不一致。当然也可以通过自定义是常数为全小数 [a-z_][a-z0-9_]{2,30}$

> pylint --const-rgx='[a-z_][a-z0-9_]{2,30}$' simplecaesar.py
-------------------------------------------------------------------
Your code has been rated at 10.00/10 (previous run: 8.42/10, +1.58)

进阶知识

1. 各异常处理方法(持续更新 …)

2. 在一个Python程序中调用 pylint

**方法1:**输出terminal

import pylint.lint
pylint_opts = ['--version']
pylint.lint.Run(pylint_opts)

方法2: 静默运行

from pylint import epylint as lint
(pylint_stdout, pylint_stderr) = lint.py_run('module_name.py', return_std=True)

# 可在py_run() 第一个参数位置添加 pylint option
from pylint import epylint as lint
(pylint_stdout, pylint_stderr) = lint.py_run('module_name.py --disable C0114', return_std=True)

消息模板选项 --msg-template="{path}:{line}: {category} ({msg_id}, {symbol}, {obj}) {msg}" 以及--reports=nepylint 模块隐式定义.

3. 配置高级操作

使用[生成默认配置文件](#3. 生成默认配置文件)操作可以简化繁琐的配置过程,快速定义默认的全面的配置选项。你有两种方式使用配置文件,第一种使用--rcfile参数,第二种 pylint 按如下顺序搜索配置文件,选择第一个出现的。

  1. pylintrc in the current working directory
  2. .pylintrc in the current working directory
  3. pyproject.toml in the current working directory, providing it has at least one tool.pylint. section.
  4. setup.cfg in the current working directory, providing it has at least one pylint. section
  5. If the current working directory is in a Python package, Pylint searches up the hierarchy of Python packages until it finds a pylintrc file. This allows you to specify coding standards on a module-by-module basis. Of course, a directory is judged to be a Python package if it contains an __init__.py file.
  6. The file named by environment variable PYLINTRC

当然你可以在基础的配置上,手动调整一些配置,如下为常见的配置:

--ignore=<file[,file...]> Files or directories to be skipped. They should be base names, not paths.

--output=<file> Specify an output file, 输出到本地文件

--output-format=<format> Select output format (text, json, custom). a comma-separated list of formats(多个格式,好像不能输出). Possible values are: json, parseable, colorized and msvs (visual studio)

--msg-template=<template> Modify text output message template. the default format:{path}:{line}:{column}: {msg_id}: {msg} ({symbol}) The format string uses the Python new format syntax and the following fields are available :

  • [path] relative path to the file
  • [abspath] absolute path to the file
  • [line] line number
  • [column] column number
  • [module] module name
  • [obj] object within the module (if any)
  • [msg] text of the message
  • [msg_id] id the message code (eg. I0011)
  • [symbol] symbolic name of the message (eg. locally-disabled)
  • [C] one letter indication of the message category
  • [category] fullname of the message category

--list-msgs Generate pylint’s messages.

--list-msgs-enabled Display a list of what messages are enabled and disabled with the given configuration.

--full-documentation Generate pylint’s full documentation, in reST format.

常用例子

pylint --output=pylint_test.json --output-format=json test.py
pylint --msg-template='{msg_id}:{line:3d},{column}: {obj}: {msg}'

Visual Studio compatible format (former 'msvs' output format):{path}({line}): [{msg_id}{obj}] {msg}

Parseable (Emacs and all, former 'parseable' output format) format: {path}:{line}: [{msg_id}({symbol}), {obj}] {msg}

4. 局部关闭某告警类型

"""pylint option block-disable"""

__revision__ = None

class Foo(object):
    """block-disable test"""

    def __init__(self):
        pass

    def meth1(self, arg):
        """this issues a message"""
        print(self)

    def meth2(self, arg):
        """and this one not 关闭一个block的unused-argument错误"""
        # pylint: disable=unused-argument
        print(self\
              + "foo")

    def meth3(self):
        """test one line disabling 关闭一行"""
        # no error
        print(self.bla) # pylint: disable=no-member
        # error
        print(self.blop)

    def meth4(self):
        """test re-enabling 重使能"""
        # pylint: disable=no-member
        # no error
        print(self.bla)
        print(self.blop)
        # pylint: enable=no-member
        # error
        print(self.blip)

    def meth5(self):
        """test IF sub-block re-enabling"""
        # pylint: disable=no-member
        # no error
        print(self.bla)
        if self.blop:
            # pylint: enable=no-member
            # error
            print(self.blip)
        else:
            # no error
            print(self.blip)
        # no error
        print(self.blip)

    def meth6(self):
        """test TRY/EXCEPT sub-block re-enabling"""
        # pylint: disable=no-member
        # no error
        print(self.bla)
        try:
            # pylint: enable=no-member
            # error
            print(self.blip)
        except UndefinedName: # pylint: disable=undefined-variable
            # no error
            print(self.blip)
        # no error
        print(self.blip)

    def meth7(self):
        """test one line block opening disabling"""
        if self.blop: # pylint: disable=no-member
            # error
            print(self.blip)
        else:
            # error
            print(self.blip)
        # error
        print(self.blip)

    def meth8(self):
        """test late disabling"""
        # error
        print(self.blip)
        # pylint: disable=no-member
        # no error
        print(self.bla)
        print(self.blop)
  1. pylint 官网

  2. Pylint-FAQs

 类似资料: