使用autopep8自動規范化python3代碼


技術背景

編碼規范是所有編程語言都有可能面臨的問題,嚴格的按照編碼規范來寫代碼,不僅能夠提高代碼的可讀性,在后續程序的可維護性上面也有較大的幫助。尤其是在開源項目中,一個具備良好編程規范的項目往往能夠吸引更多的開發者一起貢獻。這里我們介紹2款可以自動幫助我們進行代碼格式化規范的工具:autopep8以及black的安裝和基本使用方法。

autopep8的安裝

因為都是python寫的規范工具,可以用pip來直接進行版本管理和安裝:

[dechin@dechin-manjaro autopep8]$ python3 -m pip install autopep8
Requirement already satisfied: autopep8 in /home/dechin/anaconda3/lib/python3.8/site-packages (1.5.4)
Requirement already satisfied: toml in /home/dechin/anaconda3/lib/python3.8/site-packages (from autopep8) (0.10.1)
Requirement already satisfied: pycodestyle>=2.6.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from autopep8) (2.6.0)

安裝完成后,可以使用如下指令測試是否安裝成功:

[dechin@dechin-manjaro autopep8]$ autopep8 --help
usage: autopep8 [-h] [--version] [-v] [-d] [-i] [--global-config filename]
                [--ignore-local-config] [-r] [-j n] [-p n] [-a] [--experimental]
                [--exclude globs] [--list-fixes] [--ignore errors] [--select errors]
                [--max-line-length n] [--line-range line line] [--hang-closing]
                [--exit-code]
                [files [files ...]]

Automatically formats Python code to conform to the PEP 8 style guide.

positional arguments:
  files                 files to format or '-' for standard in

optional arguments:
  -h, --help            show this help message and exit
  --version             show program's version number and exit
  -v, --verbose         print verbose messages; multiple -v result in more verbose messages
  -d, --diff            print the diff for the fixed source
  -i, --in-place        make changes to files in place
  --global-config filename
                        path to a global pep8 config file; if this file does not exist then
                        this is ignored (default: /home/dechin/.config/pep8)
  --ignore-local-config
                        don't look for and apply local config files; if not passed,
                        defaults are updated with any config files in the project's root
                        directory
  -r, --recursive       run recursively over directories; must be used with --in-place or
                        --diff
  -j n, --jobs n        number of parallel jobs; match CPU count if value is less than 1
  -p n, --pep8-passes n
                        maximum number of additional pep8 passes (default: infinite)
  -a, --aggressive      enable non-whitespace changes; multiple -a result in more
                        aggressive changes
  --experimental        enable experimental fixes
  --exclude globs       exclude file/directory names that match these comma-separated globs
  --list-fixes          list codes for fixes; used by --ignore and --select
  --ignore errors       do not fix these errors/warnings (default: E226,E24,W50,W690)
  --select errors       fix only these errors/warnings (e.g. E4,W)
  --max-line-length n   set maximum allowed line length (default: 79)
  --line-range line line, --range line line
                        only fix errors found within this inclusive range of line numbers
                        (e.g. 1 99); line numbers are indexed at 1
  --hang-closing        hang-closing option passed to pycodestyle
  --exit-code           change to behavior of exit code. default behavior of return value,
                        0 is no differences, 1 is error exit. return 2 when add this
                        option. 2 is exists differences.

這些彈出的內容,同時也是autopep8的使用框架。

autopep8使用示例

這里我們使用一個官方提供的案例來進行測試,首先我們看一段非常雜亂的python代碼,這串代碼顯然是不符合python編碼規范的:

# example1.py

import math, sys;

def example1():
    ####This is a long comment. This should be wrapped to fit within 72 characters.
    some_tuple=(   1,2, 3,'a'  );
    some_variable={'long':'Long code lines should be wrapped within 79 characters.',
    'other':[math.pi, 100,200,300,9876543210,'This is a long string that goes on'],
    'more':{'inner':'This whole logical line should be wrapped.',some_tuple:[1,
    20,300,40000,500000000,60000000000000000]}}
    return (some_tuple, some_variable)
def example2(): return {'has_key() is deprecated':True}.has_key({'f':2}.has_key(''));
class Example3(   object ):
    def __init__    ( self, bar ):
     #Comments should have a space after the hash.
     if bar : bar+=1;  bar=bar* bar   ; return bar
     else:
                    some_string = """
                       Indentation in multiline strings should not be touched.
Only actual code should be reindented.
"""
                    return (sys.path, some_string)

其中各種函數都被堆到一起,雖然代碼也能夠正確的運行,但是讓人看了閱讀起來實在是非常費勁,於是我們可以用autopep8這個工具來進行格式化處理:

[dechin@dechin-manjaro autopep8]$ autopep8 --in-place --aggressive --aggressive example1.py 

運行完上述指令后,我們再來看看剛才的代碼文件:

# example1.py

import math
import sys


def example1():
    # This is a long comment. This should be wrapped to fit within 72
    # characters.
    some_tuple = (1, 2, 3, 'a')
    some_variable = {
        'long': 'Long code lines should be wrapped within 79 characters.',
        'other': [
            math.pi,
            100,
            200,
            300,
            9876543210,
            'This is a long string that goes on'],
        'more': {
            'inner': 'This whole logical line should be wrapped.',
            some_tuple: [
                1,
                20,
                300,
                40000,
                500000000,
                60000000000000000]}}
    return (some_tuple, some_variable)


def example2(): return ('' in {'f': 2}) in {'has_key() is deprecated': True}


class Example3(object):
    def __init__(self, bar):
        # Comments should have a space after the hash.
        if bar:
            bar += 1
            bar = bar * bar
            return bar
        else:
            some_string = """
                       Indentation in multiline strings should not be touched.
Only actual code should be reindented.
"""
            return (sys.path, some_string)

可以看到的是,原本代碼中存在的幾個問題,比如換行、導包、注釋等,都被格式化的處理了,這樣一行非常簡單的指令,可以幫助我們節約大量的時間。

autopep8不能解決的問題

其實autopep8也並不能一次性解決所有的PEP8規范中的問題,比如以下的一個案例:

[dechin@dechin-manjaro autopep8]$ cat example2.py 
# example2.py

print ("sjalfjlsa kkajslajs ls dlaj la jsk dka jdla kjdlksa jd alsk jdlka jsdlak jlksa jla dasajdk la jk das dada sa.")
(base) [dechin@dechin-manjaro autopep8]$ autopep8 --in-place -a -a example2.py 
(base) [dechin@dechin-manjaro autopep8]$ cat example2.py 
# example2.py

print("sjalfjlsa kkajslajs ls dlaj la jsk dka jdla kjdlksa jd alsk jdlka jsdlak jlksa jla dasajdk la jk das dada sa.")

在這個案例中,我們給出了一個代碼行長度超過規范要求的例子,但是用autopep8處理之后,代碼並沒有被改變,如果此時用flake8來進行檢測,還是能夠檢查出代碼超長的問題:

[dechin@dechin-manjaro autopep8]$ flake8
./example2.py:4:80: E501 line too long (115 > 79 characters)

因此這些自動規范化處理的工具畢竟是機器處理,要想真正的達到規范要求,我們最好還是自動規范化的工具結合規范檢查的工具,再配合人工的修改,這樣才能夠寫出質量更高的代碼。

black工具的安裝

除了autopep8之外,還有另外一款也非常常用的自動化規范工具:black,這里我們就不展開介紹其使用方法,僅介紹安裝的過程及其官方的幫助文檔:

[dechin@dechin-manjaro autopep8]$ python3 -m pip install black -i https://mirrors.cloud.tencent.com/pypi/simple 
Looking in indexes: https://mirrors.cloud.tencent.com/pypi/simple
Collecting black
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/dc/7b/5a6bbe89de849f28d7c109f5ea87b65afa5124ad615f3419e71beb29dc96/black-20.8b1.tar.gz (1.1 MB)
     |████████████████████████████████| 1.1 MB 724 kB/s 
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
    Preparing wheel metadata ... done
Requirement already satisfied: regex>=2020.1.8 in /home/dechin/anaconda3/lib/python3.8/site-packages (from black) (2020.10.15)
Requirement already satisfied: typing-extensions>=3.7.4 in /home/dechin/anaconda3/lib/python3.8/site-packages (from black) (3.7.4.3)
Requirement already satisfied: click>=7.1.2 in /home/dechin/anaconda3/lib/python3.8/site-packages (from black) (7.1.2)
Collecting pathspec<1,>=0.6
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/29/29/a465741a3d97ea3c17d21eaad4c64205428bde56742360876c4391f930d4/pathspec-0.8.1-py2.py3-none-any.whl (28 kB)
Collecting typed-ast>=1.4.0
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/0d/14/d54fd856673e3a5cb230e481bcdea04976c28b691a65029a7d45aef80575/typed_ast-1.4.3-cp38-cp38-manylinux1_x86_64.whl (774 kB)
     |████████████████████████████████| 774 kB 939 kB/s 
Requirement already satisfied: toml>=0.10.1 in /home/dechin/anaconda3/lib/python3.8/site-packages (from black) (0.10.1)
Collecting mypy-extensions>=0.4.3
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/5c/eb/975c7c080f3223a5cdaff09612f3a5221e4ba534f7039db34c35d95fa6a5/mypy_extensions-0.4.3-py2.py3-none-any.whl (4.5 kB)
Requirement already satisfied: appdirs in /home/dechin/anaconda3/lib/python3.8/site-packages (from black) (1.4.4)
Building wheels for collected packages: black
  Building wheel for black (PEP 517) ... done
  Created wheel for black: filename=black-20.8b1-py3-none-any.whl size=124184 sha256=2a1cde43fd729754692b801426aa8cd0becaabe73ae989f6caa761bac46ca9de
  Stored in directory: /home/dechin/.cache/pip/wheels/b5/b8/0f/2d0f8b6f216e8a42f90dcc4d960f30dbf8d5e08dc1b034b32c
Successfully built black
Installing collected packages: pathspec, typed-ast, mypy-extensions, black
Successfully installed black-20.8b1 mypy-extensions-0.4.3 pathspec-0.8.1 typed-ast-1.4.3

同樣的也是使用pip來進行包的安裝和管理,然后可以在命令行運行black --help查看幫助文檔,整體而言跟autopep8還是非常類似的。

[dechin@dechin-manjaro autopep8]$ black --help
Usage: black [OPTIONS] [SRC]...

  The uncompromising code formatter.

Options:
  -c, --code TEXT                 Format the code passed in as a string.
  -l, --line-length INTEGER       How many characters per line to allow.
                                  [default: 88]

  -t, --target-version [py27|py33|py34|py35|py36|py37|py38]
                                  Python versions that should be supported by
                                  Black's output. [default: per-file auto-
                                  detection]

  --pyi                           Format all input files like typing stubs
                                  regardless of file extension (useful when
                                  piping source on standard input).

  -S, --skip-string-normalization
                                  Don't normalize string quotes or prefixes.
  --check                         Don't write the files back, just return the
                                  status.  Return code 0 means nothing would
                                  change.  Return code 1 means some files
                                  would be reformatted. Return code 123 means
                                  there was an internal error.

  --diff                          Don't write the files back, just output a
                                  diff for each file on stdout.

  --color / --no-color            Show colored diff. Only applies when
                                  `--diff` is given.

  --fast / --safe                 If --fast given, skip temporary sanity
                                  checks. [default: --safe]

  --include TEXT                  A regular expression that matches files and
                                  directories that should be included on
                                  recursive searches.  An empty value means
                                  all files are included regardless of the
                                  name.  Use forward slashes for directories
                                  on all platforms (Windows, too).  Exclusions
                                  are calculated first, inclusions later.
                                  [default: \.pyi?$]

  --exclude TEXT                  A regular expression that matches files and
                                  directories that should be excluded on
                                  recursive searches.  An empty value means no
                                  paths are excluded. Use forward slashes for
                                  directories on all platforms (Windows, too).
                                  Exclusions are calculated first, inclusions
                                  later.  [default: /(\.direnv|\.eggs|\.git|\.
                                  hg|\.mypy_cache|\.nox|\.tox|\.venv|\.svn|_bu
                                  ild|buck-out|build|dist)/]

  --force-exclude TEXT            Like --exclude, but files and directories
                                  matching this regex will be excluded even
                                  when they are passed explicitly as arguments

  -q, --quiet                     Don't emit non-error messages to stderr.
                                  Errors are still emitted; silence those with
                                  2>/dev/null.

  -v, --verbose                   Also emit messages to stderr about files
                                  that were not changed or were ignored due to
                                  --exclude=.

  --version                       Show the version and exit.
  --config FILE                   Read configuration from FILE path.
  -h, --help                      Show this message and exit.

總結概要

本文主要通過介紹兩個python中常用的編碼規范格式化工具:autopep8和black來講解python編程中一些快速處理編程規范問題的方法,同時也說明了這些軟件的局限性。編程規范也是人為制定的,事實上在實際項目中,也不是所有的編程規范都需要滿足,這就需要項目的組織者或者領導者有自己的基本判斷。結合代碼規范檢查工具flake8以及文章中介紹的這些代碼規范格式化工具,最重要的還是要配合以人的判斷和調整,才能使得項目具有更好的可讀性、可維護性以及更友善的生態。

版權聲明

本文首發鏈接為:https://www.cnblogs.com/dechinphy/p/formater.html

作者ID:DechinPhy

更多原著文章請參考:https://www.cnblogs.com/dechinphy/

打賞專用鏈接:https://www.cnblogs.com/dechinphy/gallery/image/379634.html

騰訊雲專欄同步:https://cloud.tencent.com/developer/column/91958

參考鏈接

  1. https://blog.csdn.net/yjk13703623757/article/details/88793137


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM