一种基于代码对象的Python钩子函数方法和装置
技术领域
本发明涉及一种测试系统,尤其涉及一种基于代码对象的Python钩子函数方法和装置。
背景技术
随着计算机软件行业的发展,以及电子设备的硬件性能不断提高,应用程序的功能变得越来越复杂,且规模也越来越大。在应用程序的开发阶段,为了对其内部各个函数的实际调用情况进行分析,相关函数往往要被执行hook操作。对函数执行hook操作是一种监控函数运行的方法,其指通过拦截应用程序运行时对原函数的访问,并将应用程序重定向到开发人员自定义的函数上。由于开发人员在其自定义的函数上方便地调用各种测试工具,因此对函数的hook操作能够监控应用程序中关键函数的执行并修改相关函数的具体行为,从而为测试的自动化提供了很多方便。
因为在Python中,函数是以对象的形式存在;所以在Python中调用函数时,应用程序需要根据函数名字找到函数对象,从而调用相应的函数。目前,行业内对Python中的函数进行hook操作时一般采用所谓的Monkey Patch的方法。该方法通过把函数名字所对应的函数对象替换为自定义的函数对象,从而将应用程序重定向至自定义的函数对象。由于该方法可以在应用程序运行时对已有的代码进行修改,显著地提高了开发人员调试的效率,因此在行业内被广泛地使用(例如用于实现“绿色线程”的函数库eventlet)。
然而,在实际使用中,Monkey Patch的方法存在以下的缺陷:当目标函数的对象被事先保存下来(这种用法常见于回调函数的场合),此时开发人员若再采用Monkey Patch的方法调试目标函数,则由于相关的函数已经被事先保存下来,因此应用程序在调用相关的函数时,不再需要再通过函数名字访问目标函数的对象,从而无法将应用程序重定向至开发人员的自定义函数中。
发明内容
本发明的目的是解决现有技术的不足,提供一种基于代码对象的Python钩子函数方法和装置,能够获得在服务器运行时,对注册到回调函数中的函数进行监测的效果。
为了实现上述目的,本发明采用以下的技术方案。
首先,本发明提出一种基于代码对象的Python钩子函数方法,包括以下步骤:获取目标函数相对应的目标函数信息;根据所获取的目标函数信息,创建与目标函数具有相同参数类型和闭包变量个数的调试函数;分别获取的目标函数相对应的第一函数对象和调试函数相对应的第二函数对象,并将第一函数对象中func_code成员赋值给第二函数对象的func_code成员;调用目标函数以触发调试函数。其中,上述目标函数信息至少包含由以下项组成的组:目标函数的参数类型和闭包函数的闭包变量个数。
在上述方法的一个或多个实施例中,在执行上述方法前还包括以下预处理:注入运行中的服务器进程,以获取与Python虚拟机交互的shell。
在上述方法的一个或多个实施例中,第二函数对象包含打印外部日志文件的语句。
进一步地,在上述实施例中,第二函数对象所生成的外部日志文件被保存在测试服务器和/或运行测试用例的终端上。
在上述方法的一个或多个实施例中,上述调试函数是通过执行脚本创建的。
在上述方法的一个或多个实施例中,第一函数对象和调试函数相对应的第二函数对象是通过脚本获取的,且上述脚本将第一函数对象中func_code成员赋值给第二函数对象的func_code成员。
其次,本发明还提出一种基于代码对象的Python钩子函数装置,其包括以下模块:第一获取模块:用于获取目标函数相对应的目标函数信息,上述目标函数信息至少包含由以下项组成的组:目标函数的参数类型和闭包函数的闭包变量个数;创建模块,用于根据所获取的目标函数信息,创建与目标函数具有相同参数类型和闭包变量个数的调试函数;第二获取模块,用于分别获取的目标函数相对应的第一函数对象和调试函数相对应的第二函数对象,并将第一函数对象中func_code成员赋值给第二函数对象的func_code成员;调试模块,用于调用目标函数以触发调试函数。
在上述装置的一个或多个实施例中,上述装置还包括以下的预处理模块:注入模块,用于注入运行中的服务器进程,以获取与Python虚拟机交互的shell。
在上述装置的一个或多个实施例中,第二函数对象包含打印外部日志文件的语句。
进一步地,在上述实施例中,调试模块将第二函数对象所生成的外部日志文件保存在测试服务器和/或运行测试用例的终端上。
在上述装置的一个或多个实施例中,创建模块通过执行脚本创建上述调试函数。
在上述装置的一个或多个实施例中,第二获取模块通过脚本获取第一函数对象和调试函数相对应的第二函数对象,且上述脚本将第一函数对象中func_code成员赋值给第二函数对象的func_code成员。
最后,本发明还公开了一种计算机可读存储介质,其上存储有计算机指令,该指令被处理器执行时实现如前述任一项所述的方法的步骤。
本发明的有益效果为:通过创建与待监控的目标函数相对应的调试函数,将运行中的程序对目标函数的调用重定向至调试函数,提供了一种对回调函数进行监控的方式。
附图说明
图1所示为基于代码对象的Python钩子函数方法的一个实施例的流程图;
图2所示为图1所示流程的执行过程示意图;
图3所示为本发明的一个实施例保存外部日志文件方式的示意图;
图4所示为基于代码对象的Python钩子函数装置的一个实施例的模块图。
具体实施方式
以下将结合实施例和附图对本发明的构思、具体结构及产生的技术效果进行清楚、完整的描述,以充分地理解本发明的目的、方案和效果。需要说明的是,在不冲突的情况下,本申请中的实施例及实施例中的特征可以相互组合。附图中各处使用的相同的附图标记指示相同或相似的部分。
在本文中,目标函数是Python应用程序中待调试的函数,尤其是Python应用程序中的回调函数。相应地,调试函数是根据目标函数编写,用于监控目标函数执行状况的函数。在调试函数中,目标函数原有的功能可以仅部分执行或者不执行。然而,调试函数可以通过诸如将所接收的输入变量或者函数调用堆栈打印为外部日志文件的方式,向开发人员提供执行目标函数时,目标函数的外部运行环境。然而在Python中,某些目标函数由于各种原因,函数相应的对象被事先保存下来,使得此类函数被调用时可以不需要通过函数的名字访问。例如对于目标函数是回调函数的情况,此时由于目标函数在应用程序初始化的时候已经被定义,并注册相应的指针(地址)给应用程序,因此这使得目标函数的对象已被保存。当需要调用回调函数时,应用程序可以直接通过指针(地址)而不是回调函数的对象访问函数,从而无法将应用程序重定向至调试函数。
参照图1所示的方法流程图,本发明公开了一种基于代码对象的Python钩子函数方法,包括以下步骤:获取目标函数相对应的目标函数信息;根据所获取的目标函数信息,创建与目标函数具有相同参数类型和闭包变量个数的调试函数;分别获取的目标函数相对应的第一函数对象和调试函数相对应的第二函数对象,并将第一函数对象中func_code成员赋值给第二函数对象的func_code成员;调用目标函数以触发调试函数。其中,上述目标函数信息至少包含由以下项组成的组:目标函数的参数类型和闭包函数的闭包变量个数。
参照图2所示的执行过程示意图,当待调试的目标函数被应用程序回调时,由于目标函数的func_code成员已被调试函数的对应成员所赋值,因此即使目标函数已被事先保存,应用程序还是被重定向至开发人员自定义的调试函数。
在上述方法的一个实施例中,在执行上述方法前还包括以下预处理:注入运行中的服务器进程,以获取与Python虚拟机交互的shell。其中注入运行中的服务器进程可以本领域技术人员惯用技术手段实现,本发明对此不予限定。当服务器进程被注入后,上述方法可以脚本的方式加载至服务器进程中,从而由服务器进程执行相关的方法。
在上述方法的一个实施例中,第二函数对象包含打印外部日志文件的语句。上述打印语句将当前目标函数的外部运行环境,例如包括但是不限于回调函数的调用时刻、当前的函数调用堆栈,传入回调函数的所有参数的值、当前应用程序所占用的内存资源等,以方便开发人员全面了解应用程序的当前运行状况。
外部日志文件可以可读的文本文件保存。进一步地,参照图3所示的外部日志存储示意图,在上述方法的一个实施例中,第二函数对象所生成的外部日志文件被保存在测试服务器和/或运行测试用例的终端(例如开发人员个人电脑、智能手机或平板电脑)上。开发人员初步审查该外部日志文件后,可将该外部日志文件拷贝到测试服务器上,供测试人员在应用程序版本更新时进行回归测试。可替代地,测试人员也可针对该外部日志文件所保存的数据,调整测试用例。在本发明的另一个实施例中,外部日志文件可直接保存在测试服务器上。测试服务器将多台终端形成的外部日志文件汇总整理,例如可以基于收集所得的多份外部日志文件上的关键字,抓取对应的数据等本领域技术人员所熟知的自动化汇总整理方式。
在上述方法的一个或多个实施例中,上述调试函数是通过执行脚本创建的。类似地,第一函数对象和调试函数相对应的第二函数对象也是通过脚本获取的,且上述脚本将第一函数对象中func_code成员赋值给第二函数对象的func_code成员。相应的脚本文件可被注入到应用程序中,使得当应用程序调用目标函数时,调试函数被调用,从而让开发人员可以通过设置在调试函数内的测试工具,监控目标函数的调用过程。
参照图4所示的模块结构图,本发明公开了一种基于代码对象的Python钩子函数装置,包括以下模块:第一获取模块:用于获取目标函数相对应的目标函数信息;创建模块,用于根据所获取的目标函数信息,创建与目标函数具有相同参数类型和闭包变量个数的调试函数;第二获取模块,用于分别获取的目标函数相对应的第一函数对象和调试函数相对应的第二函数对象,并将第一函数对象中func_code成员赋值给第二函数对象的func_code成员;调试模块,用于调用目标函数以触发调试函数。其中,上述目标函数信息至少包含由以下项组成的组:目标函数的参数类型和闭包函数的闭包变量个数。
在上述装置的一个实施例中,上述装置还包括以下预处理模块:注入模块,用于注入运行中的服务器进程,以获取与Python虚拟机交互的shell。其中注入模块在注入运行中的服务器进程时,可以采用本领域技术人员惯用技术手段,本发明对此不予限定。当服务器进程被注入后,上述装置可以将创建模块和第二获取模块以脚本的方式加载至服务器进程中,从而由服务器进程调用相关的装置。
在上述方法的一个实施例中,第二函数对象包含打印外部日志文件的语句。上述打印语句将当前目标函数的外部运行环境,例如包括但是不限于回调函数的调用时刻、当前的函数调用堆栈,传入回调函数的所有参数的值、当前应用程序所占用的内存资源等,以方便开发人员全面了解应用程序的当前运行状况。
外部日志文件可以可读的文本文件保存。进一步地,参照图3所示的外部日志存储示意图,在上述装置的一个实施例中,第二函数对象所生成的外部日志文件被保存在测试服务器和/或运行测试用例的终端(例如开发人员个人电脑、智能手机或平板电脑)上。开发人员初步审查该外部日志文件后,可将该外部日志文件拷贝到测试服务器上,供测试人员在应用程序版本更新时进行回归测试。可替代地,测试人员也可针对该外部日志文件所保存的数据,调整测试用例。在本发明的另一个实施例中,外部日志文件可直接保存在测试服务器上。测试服务器将多台终端形成的外部日志文件汇总整理,例如可以基于收集所得的多份外部日志文件上的关键字,抓取对应的数据等本领域技术人员所熟知的自动化汇总整理方式。
在上述装置的一个或多个实施例中,创建模块通过执行脚本创建上述调试函数。类似地,第二获取模块通过脚本获取第一函数对象和调试函数相对应的第二函数对象,且上述脚本将第一函数对象中func_code成员赋值给第二函数对象的func_code成员。相应的脚本文件可被注入到应用程序中,使得当应用程序调用目标函数时,调试函数被调用,从而让开发人员可以通过设置在调试函数内的测试工具,监控目标函数的调用过程。
上述一种基于代码对象的Python钩子函数方法可以运行于桌上型计算机、笔记本、掌上电脑及云端服务器等计算设备中。上述一种基于代码对象的Python钩子函数方法可运行的装置可包括,但不仅限于,处理器、存储器。本领域技术人员可以理解,上述例子仅仅是一种基于代码对象的Python钩子函数方法的示例和装置,并不构成对一种基于代码对象的Python钩子函数方法或装置的限定,可以包括比例子更多或更少的部件,或者组合某些部件,或者不同的部件,例如上述一种基于代码对象的Python钩子函数方法还可以包括输入输出设备、网络接入设备、总线等。
所称处理器可以是中央处理单元(Central Processing Unit,CPU),还可以是其他通用处理器、数字信号处理器(Digital Signal Processor,DSP)、专用集成电路(Application Specific Integrated Circuit,ASIC)、现成可编程门阵列(Field-Programmable Gate Array,FPGA)或者其他可编程逻辑器件、分立门或者晶体管逻辑器件、分立硬件组件等。通用处理器可以是微处理器或者该处理器也可以是任何常规的处理器等,上述处理器是上述一种代码对象的Python钩子函数方法运行装置的控制中心,利用各种接口和线路连接整个一种代码对象的Python钩子函数方法可运行装置的各个部分。
上述存储器可用于存储上述计算机程序和/或模块,上述处理器通过运行或执行存储在上述存储器内的计算机程序和/或模块,以及调用存储在存储器内的数据,实现上述一种代码对象的Python钩子函数方法的各种功能。上述存储器可主要包括存储程序区和存储数据区,其中,存储程序区可存储操作系统、至少一个功能所需的应用程序(比如声音播放功能、图像播放功能等)等;存储数据区可存储根据手机的使用所创建的数据(比如音频数据、电话本等)等。此外,存储器可以包括高速随机存取存储器,还可以包括非易失性存储器,例如硬盘、内存、插接式硬盘,智能存储卡(Smart Media Card,SMC),安全数字(SecureDigital,SD)卡,闪存卡(Flash Card)、至少一个磁盘存储器件、闪存器件、或其他易失性固态存储器件。
尽管本发明的描述已经相当详尽且特别对几个上述实施例进行了描述,但其并非旨在局限于任何这些细节或实施例或任何特殊实施例,而是应当将其视作是通过参考所附权利要求考虑到现有技术为这些权利要求提供广义的可能性解释,从而有效地涵盖本发明的预定范围。此外,上文以发明人可预见的实施例对本发明进行描述,其目的是为了提供有用的描述,而那些目前尚未预见的对本发明的非实质性改动仍可代表本发明的等效改动。