python性能分析工具模块_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上的地址如下,有兴趣的可以去看看,了解一下

-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 custom.models import CustomsDeclarationLine

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

@profile

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 a

然后cd到该目录下,执行命令kernprof -l -v test.py

发现报错,无法导入其它app里的Model(数据模型),即无法导入account.models模块,然后sys.path查看当前路径,发现路径里没有account等模块的路径,然后用sys.path.append()函数加入相关路径,模块可以导入,但又出了新的问题,ImportError: Settings cannot be imported, because environment variable DJANGO_SETTINGS_MODULE is undefined.

在网上找资料解决,但还是不行,网上的解决方法都是和模板有关,但是我的代码里根本没有涉及到与模板有关的东西,后来想想,是不是待测试代码文件test.py位置放错了里呢,是不能放在与app views.py同级目录里呢?后来将其移到与manage.py同级目录里,运行后还是报错,错误同上,不能导入settings,后来联想到之前django 扩展manage命令的知识,脑海里意识到Django独立运行脚本是不是有特殊的地呢?

然后找资料,果然是,因为执行的这个Python文件时,Python文件无法找到settings文件,导致引入Models失败。所以要在脚本里添加如下代码import sys,os,django

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) #把manage.py所在目录添加到系统目录

os.environ['DJANGO_SETTINGS_MODULE'] = 'jcsbms.settings' #设置setting文件

#django.setup()#初始化Django环境,django1.4及以下版本需要这一句,由于我用的是1.8.11版本,故不需要

然后在执行命令kernprof -l -v test.py

成功了,截图如下

wKiom1fJi7GByCA0AAVW9DSY3Hk081.png-wh_500x0-wm_3-wmp_4-s_3478789785.png

其实说难也不难吧,就几个知识点:一是安装及使用,这个简单;第二是如何在django中独立运行脚本,这个之前没有碰到过,所以在这里花了很长时间去摸索,不过在这个摸索的过程中还是得到了进步。希望此文能对你有帮助,由于技术有限,如果有疑问,欢迎批评和交流!今天就讲到这里,明天讲讲怎么分析内存使用情况!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值