Python pep8 coding specification and code debugging (pdb, ipdb, debug)

Python pep8 coding specification and code debugging (pdb, ipdb, debug)

1. Python's pep8 encoding specification

I usually hear people mention PEP8, but what does it specifically refer to? "Python Enhancement Proposal # 8" (Python Enhancement Proposal No. 8) is also called PEP8, which is a code format guide compiled for Python.

Programming languages ​​are not art, but work or tools, so it is necessary to organize and follow a set of coding standards.

1. Use 4 spaces for each indentation level.
2. A maximum of 79 characters per line.
3. There are two empty lines between the definition of the top-level function (def) or class (class).
4. Use ASCII or UTF-8 encoding files. (It indicates the encoding format, ASCII encoding format or UTF-8 encoding format)
5. At the top of the file, under the comments and documentation, only one module is imported per line per import statement,
and the standard library , The import order of third-party libraries and local libraries are grouped. (The standard library is available after downloading python, that is, comes with python. If you need to download, whether it is pip or other, it is a third-party library. The local library is created by yourself)
6. In the parentheses, brackets , There is no extra space between the braces or before the brackets.
7. The naming of the class (CamelCase) is used for the naming of the class; the definition of the exception is the Error prefix (if applicable); the naming of the function is in lowercase letters separated by underscores, Such as separated_by_underscores; define private properties or methods with an underscore, such as _private

Pep8 tool for automatically checking code standards

Where does pep8 show which line violates pep8, and provides an error code for each problem, if it violates those necessary compliance rules, p will burst out an error (error code beginning with E), if If it is a subtle problem, a warning (
error code starting with W ) will be reported . The three digits following the letter are errors or warnings, from which you can see the approximate error category. For example E2 open
head space and the errors are usually related to the beginning of the mistakes usually associated with 3 blank lines, and to warn w6 beginning of this indicates that already
function through obsolete.

Code layout

1.1 Indent

  • 4 spaces for each level of indentation
  • Use vertical implicit indent or hanging indent in parentheses
  • Do n’t use Tap, let ’s not mix Tap and space
Correct demonstration
# (垂直隐式缩进)对准左括号起的第一个字符
foo = long_function_name(var_one, var_two,
                         var_three, var_four)

# (悬挂缩进) 以行首字符为基准,缩进(一般情况只需一层缩进)
foo = long_function_name(
    var_one, var_two,
    var_three, var_four)

# (悬挂缩进) 但下面情况, 需再加多一层缩进,和函数体的语句块区分开
def long_function_name(
        var_one, var_two, var_three,
        var_four):
    print(var_one)

# 右括号回退
my_list = [
    1, 2, 3,
    4, 5, 6,
]
result = some_function_that_takes_arguments(
    'a', 'b', 'c',
    'd', 'e', 'f',
)123456789101112131415161718192021222324
Error demonstration
# 使用悬挂缩进时,第一行有参数。
foo = long_function_name(var_one, var_two,
    var_three, var_four)

# 参数的悬挂缩进和后续代码块缩进不能区别。
def long_function_name(
    var_one, var_two, var_three,
    var_four):
    print(var_one)

# 右括号不回退,不推荐
my_list = [
    1, 2, 3,
    4, 5, 6,
    ]

result = some_function_that_takes_arguments(
    'a', 'b', 'c',
    'd', 'e', 'f',
    )1234567891011121314151617181920

1.2 Maximum line width

  • The maximum line width of each line does not exceed 79 characters
  • Continue lines without parentheses, use backslashes
  • No need to use backslashes for continuation in parentheses
# 无括号续行, 可使用反斜杠
with open('/path/to/some/file/you/want/to/read') as file_1, \
     open('/path/to/some/file/being/written', 'w') as file_2:
    file_2.write(file_1.read())

# 括号内续行,尽量在运算符后再续行
class Rectangle(Blob):
    def __init__(self, width, height,
                 color='black', emphasis=None, highlight=0):
        if (width == 0 and height == 0 and
                color == 'red' and emphasis == 'strong' or
                highlight > 100):
            raise ValueError("sorry, you lose")
        if width == 0 and height == 0 and (color == 'red' or
                                           emphasis is None):
            raise ValueError("I don't think so, values are %s,%s"%                             (width, height))12345678910111213141516

1.3 Blank line

  • Two blank lines are used to split the definition of top-level functions and classes
  • A single blank line is used to split the method in the class definition
  • Blank lines between logic-independent paragraphs within the function; try not to blank lines elsewhere
  • Although you can use ';', try not to write multiple statements on the same line
  • In the if / for / while statement, even if there is only one sentence in the execution statement, it must be on a new line
class A(object):     # 类的方法定义用单个空行分割
    def method1():
        pass

    def method2():
        pass

def method3():       # 两行空行分割顶层函数和类的定义
    pass12345678910

1.4 Module import

  • Each imported module should be in a separate line
  • The import sequence is as follows: first standard library, then related third-party libraries, and finally local libraries. (There must be a blank line between different types of modules, and the order of the modules in each group is arranged in ascending order from the first letter)
# 正确示范
import active   # 按模块首字母排序导入, 依此递推
import adidas
import create

# 错误示范
import sys, os, knife  # 错误:一行导入多模块

import create          # 错误:不按模块首字母导入
import active
import beyond1234567891011

1.5 String

Single quotation marks and double quotation marks have the same effect, but they must be guaranteed to exist in pairs and cannot be mixed.
(It is recommended to use double quotes for sentences and single quotes for words, but it is not mandatory.)

# 单引号和双引号效果一样

name = 'JmilkFan'
name = "Hey Guys!"1234

1.6 Spaces in expressions and statements

Avoid spaces between brackets
spam(ham[1], {eggs: 2})        # 正确示范

spam( ham[ 1 ], { eggs: 2 } )  # 错误示范123
Comma, colon, avoid spaces before semicolon
if x == 4: print x, y; x, y = y, x       # 正确示范

if x == 4 : print x , y ; x , y = y , x  # 错误示范123
There must be no space before the left parenthesis of the function call
spam(1)
dct['key'] = lst[index]     # 正确示范

spam (1)
dct ['key'] = lst [index]   # 错误示范12345
Assignment and other operators cannot add multiple spaces before and after alignment
x = 1                # 正确示范
y = 2
long_variable = 3

x             = 1    # 错误示范
y             = 2
long_variable = 31234567
Place a space on either side of the binary operator
  • Compound operators involving = (+ =,-= etc.)
  • 比较操作符 ( == , < , > , != , <> , <= , >= , in , not in , is , is not )
  • Logical operators (and, or, not)
a = b
a or b

# 括号内的操作符两边不需要空格
name = get_name(age, sex=None, city=Beijing)12345

1.7 Notes

In general, wrong comments are better than no comments. So when a piece of code changes, the first thing is to modify the comments.

  • Comment block
    • The comment block is usually applied before the code and has the same indentation as the code. Each line starts with '#', and there is a single space after #. Paragraphs are separated by lines with only "#"
# Have to define the param `args(List)`, 
# otherwise will be capture the CLI option when execute `python manage.py server`.
# oslo_config: (args if args is not None else sys.argv[1:])
CONF(args=[], default_config_files=[CONFIG_FILE])1234
  • Single-line comments (use this method as little as possible)
x = x + 1 # Compensate for border1
  • Docstring
# 多行文档, 首行首字母大写,结尾的 """ 应该单独成行
"""Return a foobang
Optional plotz says to frobnicate the bizbaz first.
"""

# 单行的文档, 结尾的 """ 在同一行。
"""Return a foobang"""1234567
  • Write docstrings for shared modules, functions, classes, methods; non-shared is not necessary to write docstrings, but you can write comments (on the next line of def)
  • Avoid unnecessary comments

1.8 Naming rules

  • Package and module names
    Package and module names should be short, all in lowercase letters, and multiple underscores can be connected by single underscores.
  • The class name
    follows the hump name.
class MyClass(object):
    pass12
  • Global variable names
    Global variable names should be used only within the module as much as possible. For modules that may from moduleName import variableNamebe imported using statements , __all__mechanisms should be used to prevent global variables from being imported by other modules, or a leading underscore should be added at the beginning of the global variable name.
_name = 'name'1
  • Function name
    Function name should be all lowercase concave hump rules.
vcenter_connection = ''1
  • Constant names
    Constants are all represented by the concave hump rule of capital letters, usually defined in the top cell of the module.
MAX_OVERFLOW = ''
TOTAL = 112
  • Method name and instance variables
    • Use underscores at the beginning of non-public methods and instance variables
    • Sometimes, in order to avoid conflicts with subclass naming, the two leading underscores
      need to be noted: If the attribute name of class Foo is a, the attribute cannot be accessed in the way of Foo.a. (Accessed via Foo._Foo__a), so usually double leading underscores are only used to avoid naming conflicts with properties of the base class.

2. Programming suggestions

  • Coding should consider the efficiency of other Python implementations, such as the operator '+' is very efficient in CPython, but very low in Jython
  • For comparison of None, use is or is not instead of ==; use 'is''is not' instead of '==' whenever possible; use is not instead of not… is, the former is more readable
if foo is not None     # Yes

if not foo is None     # No123
if x is not None       # if x is not None 要优于if x

if x123
  • Use the function definition keyword def instead of lambda to assign the identifier, which is more suitable for callback and string representation
def f(x):              # Yes
    return 2*x

f = lambda x: 2*x      # No1234
  • The exception class should inherit from Exception, not BaseException; try to specify specific exceptions when catching exceptions, try not to use except Exception; what should be caught, not the problem
try:                                   # Yes (捕获具体异常)
    import platform_specific_module    
except ImportError:
    platform_specific_module = None

try:                                   # No (不要全局捕获)
    import platform_specific_module
except:
    platform_specific_module = None123456789
  • The code in the try / except clause should be as small as possible to avoid shielding other errors
try:                            # Yes
    value = collection[key]
except KeyError:
    return key_not_found(key)
else:
    return handle_value(value)

try:                            # No
    return handle_value(collection[key])
except KeyError:
    # 可能会捕捉到handle_value()中的 KeyError, 而不是collection的
    return key_not_found(key)12345678910111213
  • The function or method should return None when there is no return value
def foo():        # Yes
    return None

def foo():        # No
    return12345
  • Use the string method instead of the string module
    Python 2.0. The string method is always faster afterwards, and uses the same API as the Unicode string
  • Use .startswith () and .endswith () instead of string slicing to check the prefix and suffix
    startswith () and endswith are more concise and help reduce errors
if foo.startswith('bar'):   # Yes

if foo[:3] == 'bar':        # No123
  • Use isinstance () to compare object types
if isinstance(obj, int):   # Yes

if type(obj) is type(1):   # No123
  • Analyzing sequence empty or not empty
    bool empty sequence type object to False:
if not seq:       # Yes
   pass
if seq:
   pass

if len(seq):      # No
   pass
if not len(seq):
   pass123456789
  • Don't use == for bool comparison
 # Yes
if greeting:          
   pass

# No
if greeting == True
   pass
if greeting is True: # Worse
   pass123456789
  • Do not end the string with spaces
  • Binary data judgment if boolvaluemethod
  • Use Map and Reduce, do not use loops

Second, pdbcode debugging

The probability that the program can be written once and run normally is very small, basically not exceeding 1%. There will always be various bugs that need to be fixed. Some bugs are very simple. You can know by looking at the error message. Some bugs are very complicated. We need to know which variables have the correct values ​​and which variables have the wrong values. To fix the bug.

Install ipdb library

PS G:\四期\python> pip install pdb

The contents of the G: \ Fourth Phase \ python \ 4 \ 1.py file are as follows:

import pdb
s = '0'
n = int(s)
pdb.set_trace()
print(10/n)

Debug

PS G:\四期\python\4> python 2.py
> g:\四期\python\4\2.py(5)<module>()
-> print(10/n)

1. Use pdb for debugging:

pdb is a package that comes with Python. It provides an interactive source code debugging function for Python programs. The main features include setting breakpoints, single-step debugging, entering function debugging, viewing current code, viewing stack fragments, and dynamically changing variables. Value etc. pdb provides some commonly used debugging commands, see Table 1 for details.

pdb common commands

command Explanation
break or b set a breakpoint Set a breakpoint
continue or c Continue to execute the program
list or l View the current line of code
step or s Entry function
return or r Execute code until return from current function
exit or q Abort and exit
next or n Execute next line
pp Print the value of a variable
help help

The following describes how to use pdb to debug with specific examples.

2. Sample test code

 import pdb 
 a = "aaa"
 pdb.set_trace() 
 b = "bbb"
 c = "ccc"
 final = a + b + c 
 print final

Start debugging: run the script directly, it will stay at pdb.set_trace (), select n + enter to execute the current statement. After pressing n + enter for the first time, you can press enter directly to repeat the last debug command.

(1) Debugging with pdb

[root@rcc-pok-idg-2255 ~]#  python epdb1.py 
 > /root/epdb1.py(4)?() 
 -> b = "bbb"
 (Pdb) n 
 > /root/epdb1.py(5)?() 
 -> c = "ccc"
 (Pdb) 
 > /root/epdb1.py(6)?() 
 -> final = a + b + c 
 (Pdb) list 
  1     import pdb 
  2     a = "aaa"
  3     pdb.set_trace() 
  4     b = "bbb"
  5     c = "ccc"
  6  -> final = a + b + c 
  7     print final 
 [EOF] 
 (Pdb) 
 [EOF] 
 (Pdb) n 
 > /root/epdb1.py(7)?() 
 -> print final 
 (Pdb)

Exit debug: Use quit or q to exit the current debug, but quit will exit the program in a very rude way, and the result is a direct crash.

(2) Exit debug

[root@rcc-pok-idg-2255 ~]#  python epdb1.py 
 > /root/epdb1.py(4)?() 
 -> b = "bbb"
 (Pdb) n 
 > /root/epdb1.py(5)?() 
 -> c = "ccc"
 (Pdb) q 
 Traceback (most recent call last): 
  File "epdb1.py", line 5, in ? 
    c = "ccc"
  File "epdb1.py", line 5, in ? 
    c = "ccc"
  File "/usr/lib64/python2.4/bdb.py", line 48, in trace_dispatch 
    return self.dispatch_line(frame) 
  File "/usr/lib64/python2.4/bdb.py", line 67, in dispatch_line 
    if self.quitting: raise BdbQuit 
 bdb.BdbQuit

Print the value of the variable: If you need to print the value of the variable during debugging, you can directly use p plus the variable name, but it should be noted that the specific value can only be seen after the current statement has been executed, otherwise it will Report NameError: <exceptions.NameError… ....> error.

(3) Print variables during debugging

[root@rcc-pok-idg-2255 ~]#  python epdb1.py 
 > /root/epdb1.py(4)?() 
 -> b = "bbb"
 (Pdb) n 
 > /root/epdb1.py(5)?() 
 -> c = "ccc"
 (Pdb) p b 
'bbb'
 (Pdb) 
'bbb'
 (Pdb) n 
 > /root/epdb1.py(6)?() 
 -> final = a + b + c 
 (Pdb) p c 
'ccc'
 (Pdb) p final 
 *** NameError: <exceptions.NameError instance at 0x1551b710 > 
 (Pdb) n 
 > /root/epdb1.py(7)?() 
 -> print final 
 (Pdb) p final 
'aaabbbccc'
 (Pdb)

Use c to stop the current debug and continue the program execution. If set_statement () continues to be declared in the following program, it will re-enter the debug state, and readers can add set_trace () to verify before the code print final.

(4) Stop debugging and continue to execute the program

[root@rcc-pok-idg-2255 ~]#  python epdb1.py 
 > /root/epdb1.py(4)?() 
 -> b = "bbb"
 (Pdb) n 
 > /root/epdb1.py(5)?() 
 -> c = "ccc"
 (Pdb) c 
 aaabbbccc

Display code: It is not necessary to remember the current code block when debugging. If you want to view the specific code block, you can display it by using the list or l command. list will use arrows-> to point to the current debug statement.

(5) Display code during debugging

[root@rcc-pok-idg-2255 ~]#  python epdb1.py 
 > /root/epdb1.py(4)?() 
 -> b = "bbb"
 (Pdb) list 
  1     import pdb 
  2     a = "aaa"
  3     pdb.set_trace() 
  4  -> b = "bbb"
  5     c = "ccc"
  6     final = a + b + c 
  7     pdb.set_trace() 
  8     print final 
 [EOF] 
 (Pdb) c 
 > /root/epdb1.py(8)?() 
 -> print final 
 (Pdb) list 
  3     pdb.set_trace() 
  4     b = "bbb"
  5     c = "ccc"
  6     final = a + b + c 
  7     pdb.set_trace() 
  8  -> print final 
 [EOF] 
 (Pdb)

Debug when using functions

(6) Examples of using functions

import pdb 
 def combine(s1,s2):      # define subroutine combine, which... 
    s3 = s1 + s2 + s1    # sandwiches s2 between copies of s1, ... 
    s3 = '"' + s3 +'"'   # encloses it in double quotes,... 
    return s3            # and returns it. 
 a = "aaa"
 pdb.set_trace() 
 b = "bbb"
 c = "ccc"
 final = combine(a,b) 
 print final

If you use n directly for debugging, then when final = combine (a, b) is used, it will be treated as an ordinary assignment statement and you will enter print final. If you want to debug the function, how to deal with it? You can directly use s to enter the function block. The single-step debugging in the function is similar to the introduction above. If you don't want to step through the function, you can press r directly at the breakpoint to exit to the calling place.

(8) Debug the function

[root@rcc-pok-idg-2255 ~]# python epdb2.py 
 > /root/epdb2.py(10)?() 
 -> b = "bbb"
 (Pdb) n 
 > /root/epdb2.py(11)?() 
 -> c = "ccc"
 (Pdb) n 
 > /root/epdb2.py(12)?() 
 -> final = combine(a,b) 
 (Pdb) s 
 --Call-- 
 > /root/epdb2.py(3)combine() 
 -> def combine(s1,s2):      # define subroutine combine, which... 
 (Pdb) n 
 > /root/epdb2.py(4)combine() 
 -> s3 = s1 + s2 + s1    # sandwiches s2 between copies of s1, ... 
 (Pdb) list 
  1     import pdb 
  2 
  3     def combine(s1,s2):      # define subroutine combine, which... 
  4  ->     s3 = s1 + s2 + s1    # sandwiches s2 between copies of s1, ... 
  5         s3 = '"' + s3 +'"'   # encloses it in double quotes,... 
  6         return s3            # and returns it. 
  7 
  8     a = "aaa"
  9     pdb.set_trace() 
 10     b = "bbb"
 11     c = "ccc"
 (Pdb) n 
 > /root/epdb2.py(5)combine() 
 -> s3 = '"' + s3 +'"'   # encloses it in double quotes,... 
 (Pdb) n 
 > /root/epdb2.py(6)combine() 
 -> return s3            # and returns it. 
 (Pdb) n 
 --Return-- 
 > /root/epdb2.py(6)combine()->'"aaabbbaaa"'
 -> return s3            # and returns it. 
 (Pdb) n 
 > /root/epdb2.py(13)?() 
 -> print final 
 (Pdb)

Change the value dynamically during debugging. The value of the variable can be changed dynamically during debugging, as shown in the following example. It should be noted that there is an error below, because b has been assigned, if you want to change the assignment of b, you should use it! B.

(7) Dynamically change the value during debugging

[root@rcc-pok-idg-2255 ~]# python epdb2.py 
 > /root/epdb2.py(10)?() 
 -> b = "bbb"
 (Pdb) var = "1234"
 (Pdb) b = "avfe"
 *** The specified object '= "avfe"' is not a function 
 or was not found along sys.path. 
 (Pdb) !b="afdfd"
 (Pdb)

supplement

  • To enter debug mode from the command line:python -m pdb demo.py
  • Press the Enterkey in the debug mode to execute the previous command.
  • Use PDB in ipython (better experience):%run -d demo.py

Reference 1

Reference 2

Guess you like

Origin blog.51cto.com/14320361/2488895