9.1 Debugging
Is regularly backed up to a programming key - no matter how little our machines, operating systems, and how reliable the probability of occurrence of a failure - because failure is still likely to occur. It is generally coarse-grained backup - backup file is before a few hours, or even days before.
9.1.1 grammar mistakes
if True
print("stupid!!!")
else:
print("You will never see me...")
File "C:/Py/modeltest.py", line 5
if True
^
SyntaxError: invalid syntax
In the above example, if the rear forget to add a ":", so the error.
try:
s = "Tomorrow is a new day, {0}"
s2 = "gone with the wind..."
print(s.format(s2)
except ValueError as err:
print(err)
File "C:/Py/modeltest.py", line 10
except ValueError as err:
^
SyntaxError: invalid syntax
See the example above, in fact, being given location and no errors, the real mistake is the print fewer side brackets, but did not realize the error in Python to run here when the brackets as possible through branches, it displays an error in the next line.
9.1.2 handle runtime errors
pass
9.1.3 debugging science
If the program can run, but the program or inconsistent behavior and expectations of need, there is a logic error bug-- must clear the program instructions. The best way to clear this type of error is the first to use TDD (test-driven development) to prevent this type of error occurs, however, there is always some bug does not avoid, therefore, even if the use of TDD, debugging still must learn and master skill.
Is clearly a bug, we must take the following step:
- Reproduction bug
- Positioning bug
- Bug fixes
- The repair of test
Pycharm Debug debugging experience - pick up & drop wrench keyboard
9.2 Unit Testing
Unit Test - test the individual functions, classes, and methods, to ensure that it complies with expected behavior.
Just as we did before:
if __name__ == "__main__":
import doctest
doctest.testmod()
Another method is to create a separate doctest execution of the test program using uniitest module. unittest module can create test cases based on doctests without guidance program or module contains anything - as long as it contains guidance doctest can be.
We have created a docunit.py program:
def test(x):
"""
>>> test(-1)
'hahahaha'
>>> test(1)
'lalalala'
>>> test('1')
'wuwuwuwuwuwu'
"""
s1 = "hahahahha"
s2 = "lalalalala"
s3 = "wuwuwuwuwuwu"
try:
if x <= 0:
return s1
else:
return s2
except:
return s3
Note that if you run the test, the former two strips to be wrong, because they do not match.
Then create a new program:
import doctest
import unittest
import docunit
suite = unittest.TestSuite()
suite.addTest(doctest.DocTestSuite(docunit))
runner = unittest.TextTestRunner()
print(runner.run(suite))
Note that the third import in their own program, the output is:
<unittest.runner.TextTestResult run=1 errors=0 failures=1>
F
======================================================================
FAIL: test (docunit)
Doctest: docunit.test
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Ana\lib\doctest.py", line 2198, in runTest
raise self.failureException(self.format_failure(new.getvalue()))
AssertionError: Failed doctest test for docunit.test
File "C:\Py\docunit.py", line 7, in test
----------------------------------------------------------------------
File "C:\Py\docunit.py", line 9, in docunit.test
Failed example:
test(-1)
Expected:
'hahahaha'
Got:
'hahahahha'
----------------------------------------------------------------------
File "C:\Py\docunit.py", line 11, in docunit.test
Failed example:
test(1)
Expected:
'lalalala'
Got:
'lalalalala'
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures=1)
Process finished with exit code 0
But, this time, we write the program name of the program, you must be a valid module name.
unittest module defines four key concepts. The test fixture is a term used to describe a test to create (and exhausted after cleaning it) code is necessary, and a typical example is to create an input file used in the test, with the final result output file erasing input file. Test Suite is a set of test cases. It is the basic unit test test. Test runs is performing one or more test suite object.
Typically, the test suite is achieved by subclassing unittest.TestCase, where each method name beginning with "test" is a test case. If we need to complete any method of creation, you can be in a setUp (named) in realization; similarly, for any clean-up operation, can also be a method called tearDown () implementation. In internal testing, a large number of available unittest.TestCase method we use, including assertTrue (), assertEqual (), assertAlmostEqual () ( useful for testing floating point), assertRaises () and more, also includes corresponding inverse method such assertFalse (), assertNotEqual (), faillfEqual (), failUnlessEqual () and the like.
Here is an example, because they do not know what a compile, use one of the most simple, just to illustrate how to use this unittest.
import unittest
class List(list):
def plus(self, other):
return list(set(self + other))
class TestList(unittest.TestCase):
def setUp(self):
self.list1 = List(range(3))
self.list2 = list(range(2, 5))
def test_list_add(self):
addlist = self.list1 + self.list2
self.assertEqual(
addlist, [0, 1, 2, 2, 3, 4]
)
def test_list_plus(self):
pluslist = self.list1.plus(self.list2)
self.assertNotEqual(
pluslist, [0, 1, 2, 2, 3, 4]
)
def process():
self.list2.plus(self.list1)
self.assertRaises(
AttributeError, process #注意assertRaises的第二项必须callable Obj
)
def tearDown(self):
"""
我不知道这么做有没有用
:return:
"""
del self
if __name__ == "__main__":
suite = unittest.TestLoader().loadTestsFromTestCase(
TestList
)
runner = unittest.TextTestRunner()
print(runner.run(suite))
More functions in the blog, quite detailed:
Python's unittest unit testing framework assertion finishing Summary - black-faced fox
9.3 Profiling
Some reasonable Python programming style, to improve application performance is not without benefits:
- Need read-only sequence is not preferable to use the list of tuples;
- Using generators, rather than creating large lists and tuples and iterate on it
- Python make use of built-in data structures --dicts, list, tuples-- not implement their own definition structure
- When small strings to produce a large, small string not connected, but accumulate in the list, the final list of strings into a single string binding
- Finally, if an object property is used many times to access, or access it from a data structure, then create and use a local variable to access the object when good practice.
In jupiter notebook inside a cell run time %% time output of a single, %% timeit output runs 100,000 times? Between the average.
Use timeit modules:
import timeit
def function_a(x, y):
for i in range(10000):
x + y
def function_b(x, y):
for i in range(10000):
x * y
def function_c(x, y):
for i in range(10000):
x / y
if __name__ == "__main__":
repeats = 1000
X = 123.123
Y = 43.432
for function in ("function_a", "function_b",
"function_c"):
t = timeit.Timer("{0}(X, Y)".format(function),
"from __main__ import {0}, X, Y".format(function))
sec = t.timeit(repeats) / repeats
print("{function}() {sec:.6f} sec".format(**locals()))
Wherein timeit.Timer () function is the first parameter, we need to perform a string, the second parameter is an executable string, it is used to provide parameters.
function_a() 0.000386 sec
function_b() 0.000384 sec
function_c() 0.000392 sec
Using cProfile module, it will be more easily and in detail to give an indication of the running time:
import cProfile
import time
def function_a(x, y):
for i in range(10000):
function_f(x, y)
function_d()
def function_b(x, y):
for i in range(10000):
function_f(x, y)
function_d()
function_d()
def function_c(x, y):
for i in range(10000):
function_f(x, y)
function_d()
function_d()
function_d()
def function_d():
time.sleep(0.01)
def function_f(x, y):
x * y
if __name__ == "__main__":
repeats = 1000
X = 123.123
Y = 43.432
for function in ("function_a", "function_b",
"function_c"):
cProfile.run("for i in range(1000): {0}(X, Y)"
.format(function))
10003003 function calls in 16.040 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.007 0.007 16.040 16.040 <string>:1(<module>)
1000 3.878 0.004 16.033 0.016 modeltest.py:13(function_a)
1000 0.006 0.000 10.241 0.010 modeltest.py:31(function_d)
10000000 1.915 0.000 1.915 0.000 modeltest.py:34(function_f)
1 0.000 0.000 16.040 16.040 {built-in method builtins.exec}
1000 10.235 0.010 10.235 0.010 {built-in method time.sleep}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
10005003 function calls in 28.183 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.008 0.008 28.183 28.183 <string>:1(<module>)
1000 4.873 0.005 28.175 0.028 modeltest.py:18(function_b)
2000 0.015 0.000 20.903 0.010 modeltest.py:31(function_d)
10000000 2.399 0.000 2.399 0.000 modeltest.py:34(function_f)
1 0.000 0.000 28.183 28.183 {built-in method builtins.exec}
2000 20.887 0.010 20.887 0.010 {built-in method time.sleep}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
10007003 function calls in 38.968 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.008 0.008 38.968 38.968 <string>:1(<module>)
1000 5.004 0.005 38.959 0.039 modeltest.py:24(function_c)
3000 0.024 0.000 31.498 0.010 modeltest.py:31(function_d)
10000000 2.457 0.000 2.457 0.000 modeltest.py:34(function_f)
1 0.000 0.000 38.968 38.968 {built-in method builtins.exec}
3000 31.474 0.010 31.474 0.010 {built-in method time.sleep}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
ncalls: the number of calls to
tottime: total time spent in a function, but sent other internal functions of time spent in a function call
percall: tottime / ncalls average time of each call function
cumtime: cumulative time list the time spent in a function, function calls and other functions include time spent inside
PerCall (second): shows the average time of a function call, a function of wrapping time consuming it invokes
Reproduced in: https: //www.jianshu.com/p/9d44767f913c