标签:python 性能分析 django line_profiler
昨天下班前写了一段后端程序,然后运行后,发现网页打开速度有点慢,不太理想(因为要去后台数据库进行大量数据查询,而且还要进行运算,所以速度有点慢),然后想到有没有专业的工具对代码块进行性能分析呢?之前一直都是用datetime模块来分析,实例如下:
#coding=utf-8 import datetime def f(x,y): t1 = datetime.datetime.now() a = x + y t2 = datetime.datetime.now() print t2-t1 return a f(1,2)
就是用这种比较笨的方法吧,写大量的datetime.datetime.now()函数。
今天想想能不能有更好的工具或者方法来分析python代码块的性能呢?然后就在网上找到了,就是line_profiler工具,使用它可以查看程序中每行代码多快多频繁的被执行。
用pip安装非常简单方便,命令如下:
pip install line_profiler
一旦安装完成,将会有一个称做“line_profiler”的新模组和一个“kernprof.py”可执行脚本。
想要使用该工具,首先修改你的源代码,在想要测量的函数上装饰@profile装饰器。不要担心,不需要导入任何模组。kernprof.py脚本将会在执行的时候将它自动地注入到你的脚本的运行时。
如下面例子test.py
@profile def run(): a = [1]*100 b = [x*x*x for x in a ] c = [x for x in b] d = c*2 run()
运行指令:
kernprof.py -l -v test.py
但是有个问题,我安装的line_profiler是1.10版本,执行上面的命令会报错,提示没有kernprof命令,在网上找资料,都是这样的呀,是不是安装错误呀,后来想想,试着去掉kernprof后面的.py,结果就可以了,即kernprof -l -v test.py
然后去GitHub上找该项目的源码以及说明文档,发现1.10版本的使用方法确实不需要.py了, 该项目在GitHub上的地址如下,有兴趣的可以去看看,了解一下
https://github.com/rkern/line_profiler
-l表示动态插入profile.
-v 当程序运行结束后,将结果输出到标准输出,而不是到文件中。
其他用法可以参看kernprof帮助:kernprof –help。
结果很详细,给出了每行运行时间,百分比等
用起来确实很简单,但怎么在Django中用呢?Django后端程序避免不了查询数据库等一系列动作,不像上面那个例子那么简单,在这里我遇到了很大的困难,先开始是将待分析的代码块单独拿出来放在了一个与django app的views.py同级目录里(该文件命名为test.py),
代码如下:
from account.models import Voucher, VoucherLine from sale.models import SaleOrder,SaleOrderLine #from purchases.models import ShipOrderLine,ShipOrder from custom.models import CustomsDeclarationLine @profile def _get_saleorderline_field_sum(saleorderslines): """ Args: saleorderslines: Returns: """ sale_total = 0.0 purchases_total = {‘USD‘:0.0,‘HKD‘:0.0,‘CNY‘:0.0} if saleorderslines: for one in saleorderslines: sale_total += int(one.product_qty) * float(one.sale_unit_price) if one.purchase_currency == "$": purchases_total[‘USD‘] += int(one.product_qty) * float(one.purchase_unit_price) elif one.purchase_currency == "HK$": purchases_total[‘HKD‘] += int(one.product_qty) * float(one.purchase_unit_price) else: purchases_total[‘CNY‘] += int(one.product_qty) * float(one.purchase_unit_price) return sale_total,purchases_total else: return sale_total,purchases_total def _get_customsdeclarationline_field_sum(customlines): """ Args: customlines: Returns: """ vat_total = 0.0 agent_fee_total = 0.0 custom_duties_total = 0.0 if customlines: for one in customlines: vat_total += float(one.vat) agent_fee_total += float(one.agent_fee) custom_duties_total += float(one.custom_duties) return vat_total,agent_fee_total,custom_duties_total else: return vat_total,agent_fee_total,custom_duties_total def api_get_saleorder_detail_by_voucher(number): Args: number: Returns: """ data = {‘voucher_number‘:number} voucher = Voucher.objects.get(number=number) data[‘voucher_amount‘] = float(voucher.amount) data[‘voucher_currency‘] = voucher.currency.symbol#收据上的货币种类 data[‘create_time‘] = voucher.create_time.strftime("%Y-%m-%d %H:%M:%S")#收据创建时间 data[‘partner_name‘] = voucher.partner.name #data[‘create_user‘] = voucher.create_user.get_full_name voucherlines = VoucherLine.objects.filter(voucher=voucher) voucherlines = voucherlines.filter(type="cr") so_name_list = [one.move_line.ref for one in voucherlines] try: data[‘reconcile_date‘] = [one.write_time.strftime("%Y-%m-%d %H:%M:%S") for one in voucherlines if one.reconcile is not None][0] except: data[‘reconcile_date‘] = voucher.write_time.strftime("%Y-%m-%d %H:%M:%S") saleorders = SaleOrder.objects.filter(name__in=so_name_list).exclude(state=‘cancel‘) if saleorders: data[‘sale_currency‘] = saleorders[0].moneytype else: data[‘sale_currency‘] = ‘none‘ saleorderlines = SaleOrderLine.objects.filter(order__in=saleorders) sale_total, purchases_total = _get_saleorderline_field_sum(saleorderlines) #a = saleorderlines.values(‘id‘) sol_id_list = [one.pk for one in saleorderlines] #sol_id_list = [one[‘id‘] for one in a] customlines = CustomsDeclarationLine.objects.filter(sale_order_line__in=sol_id_list) vat_total,agent_fee_total,custom_duties_total = _get_customsdeclarationline_field_sum(customlines) data[‘sale_total‘] = sale_total data[‘purchases_total‘] = purchases_total #data[‘purchases_currency‘] = purchases_currency data[‘vat_total‘] = vat_total data[‘agent_fee_total‘] = agent_fee_total data[‘custom_duties_total‘] = custom_duties_total return data a = api_get_saleorder_detail_by_voucher("BNK58/2016/16812") print aPython,django:用line_profiler工具分析代码的性能
扫一扫手机访问
