c++ 调用python 传入字符串_《利用Python进行数据分析》学习笔记2 - IPython

21468c0cb3aaf767935e389cf20cc765.png

[第三章 Part2]

交互式调试器

  1. 调试代码最佳时机就是刚刚出错时,%debug命令(发生异常之后马上输入)将会调用“事后”调试器,并直接跳转到引发异常的栈帧(stack frame)。
  2. 进入调试器后提示符变为 ipdb>
  3. 输入u(或up)和d(或down)即可切换栈跟踪的各级别。
  4. 执行%pdb命令可以让IPython出现异常之后自动调用调试器。(pdb是python debug的缩写吧?)
  5. 设置断点或单步调试: 使用-d选项的%run命令,然后运行之后,必须立即输入s(或step)才能进入脚本。然后输入行号设置断点,使用c(或continue)是脚本运行到断点处。然后输入n(或next)可打不进入断点处,直到前进到发生错误的那一行。
  6. 注意:调试器命令的优先级高于变量名,在变量前面加上感叹号(!)即可查看其内容。
  7. 利用IPython作为调试器必须多实践,熟练后效率更高。
  8. IPython调试器命令

cfa931612f9682b015a8bf4f99de543e.png

调试器的其他使用场景

1bdebe9c166841189471550c76e51fd1.png
  1. 使用set_trace这个特别的函数(以pdb.set_trace命名),硬编码的比较随意。可以直接将上述两个函数添加到IPython的配置中。
  2. 第一个set_trace函数可以放到代码中任何希望停下来的地方。(比如发生异常的地方)。
  3. 按下c(或continue)仍会恢复代码执行。
  4. 第二个debug函数能够直接在任意函数上使用调试器。例如下面定义f函数之后用debug直接传入参数计算。

f4d3330f89a20235ba199869585bc08d.png
f()函数

e38249def15e4dd9adc66e129ac3ed29.png
debug直接传入参数给f()函数

结合%run -d执行脚本,在后面再加上 -b 和一个行号可以直接在调试器启动时自动设置断点。

In[2]: %run -d -b2 xxx/xxx/xx.py

测试代码的执行时间:%time和%timeit

使用内置的time模块及其time.clock和time.time函数手工测试代码执行时间是一件令人烦闷的事情,代码如下:

import time
start = time.time()
for i in range(iterations):
    # 这里放一些待执行的代码
    elapse_per = (time.time() - start) / iterations

%time一次执行一条语句,然后报告总体执行时间。

例如下面是一个有60万字符串的数组,以及两个不同的“选出其中以foo开头的字符串”的方法:

# 一个非常大的字符串数组
strings = ['foo', 'foobar', 'baz', 'qux', 'python', 'Guido Van Rossum'] * 100000
method1 = [x for x in strings if x.startswith('foo')]
method2 = [x for x in string if x[:3] == 'foo']

看上去感觉性能表现应该差不多,对吧?那用%time来确认一下:

cd6b187162bdb9094bbc26498ae9f0c0.png

如果多次执行%time,结果会变化。为了更精确,可使用%timeit。它会自动多次执行然后产生一个非常精确的平均执行时间。

fcedd4194ecad03fcd02fcc520383193.png

对于执行时间微妙或者纳秒级的分析,%timeit非常有用,体会下列执行100万次的结果:

325e6740e73641585274c4da463e5b70.png

基本性能分析:%prun和%run -p

Python的主要性能分析工具是cProfile模块,一般是在命令行上使用。

import numpy as np
from numpy.linalg import eigvals

def run_experiment(niter=100):
    k = 100
    results = []
    for _ in range(niter):
        mat = np.random.randn(k,k)
        max_eigenvalue = np.abs(eigvals(mat)).max()
        results.append(max_eigenvalue)
    return results
some_results = run_experiment()
print('Largest one we saw: %s' %np.max(some_results))

注意:书中以Python2.7为例,使用了xrange。python3中取消了xrange,仅有range。

保存为test.py后,保存到命令行根目录后,运行cProfile。

python -m cProfile test.py

2856c01418bdd2147549ad4f990ae0a4.png

执行之后按函数名排序,很难发现哪里最花时间。因此通常用-s标记指定一个排序规则。

python -m cProfile -s cumulative test.py

da4f62ffc7269f50b4201fbeec60f165.png

注意:如果一个函数调用了别的函数,计时器是不会停下来重新计时的。cProfile记录的是各函数调用的起始和结束时间,并依此计算总时间。

IPython提供了%prun和%run -p命令分析性能。其中%prun的格式和cProfile差不多,但它分析的是Python语句而不是整个.py文件。

04a52f1dc064528f78aa415d87db1f90.png

执行

%run -p -s cumulative test.py

也能达到cProfile命令行命令一样的效果,但无需退出IPython。

745a79e208296617521bac542b1de751.png

逐行分析函数性能

有时候利用%prun得到的信息不足以说明函数执行时间或难以理解。这时候可以使用line_profiler的小型库。其中有魔术函数%lprun,可以对一个或多个函数进行逐行性能分析。可以修改IPython配置以启用这个扩展,代码如下:

# A list of dotted module names of IPython extensions to load.
c.TerminalIPythonApp.extensions = ['line_profiler']

%lprun的通用语法为:

%lprun -f function1 -f function2 statement_to_profile

了解:通常%prun(cProfile)做“宏观的”性能分析,而%lprun(line_profiler)做“微观的”性能分析。

待续......

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值