测评系统揭秘——从Python程序设计测评说起
作者: 虞颖健 倪俊杰
编者按:随着计算机技术和用户需求的不断发展,人们对测评系统的要求越来越多,已经不再停留于简单客观题目的评判,而是要求能涉及程序设计、填空、论述等主观题型,甚至是作文批改、语义分析、多媒体文件作品的自动评判等。本期文章,我们先从程序设计题的评判说起,一起来揭秘测评系统背后的故事。
新一轮的课程改革大幅增加了高中信息技术新教材程序设计相关内容的比重,大数据、物联网、人工智能等内容进入了信息技术新版教材,新版教材的编程语言换成了在以上领域应用广泛的Python。Python程序设计教学在新课程的教学中具有举足轻重的地位。程序设计测评系统能够即时检验学生编写的程序代码是否正确,教学需求也日益增强。相比传统的课堂教学模式,采用程序测评系统的程序设计课堂教学能够根据测评系统的实时反馈及时掌握学生的学习情况,进而能更好地调整课堂教学,提升课堂教学的有效性。
● 在线测评系统的需求
在线测评系统(Online Judge,简称OJ系统)是目前广泛使用的主流程序测评系统。OJ系统是一个在线判题系统,用户可以在线提交程序源代码,系统通过预先设计的测试数据来检验程序源代码的正确性。用户提交的程序在OJ系统下执行时将受到比较严格的限制,包括运行时间限制、内存使用限制和安全限制等。用户程序执行的结果将被OJ系统捕捉并保存,然后再转交给一个裁判程序。该裁判程序或者比较用户程序的输出数据和标准输出样例的差别,或者检验用户程序的输出数据是否满足一定的逻辑条件。国内较为著名的OJ系统有POJ(北京大学)、ZOJ(浙江大学)、HDOJ(杭州电子科技大学)。
传统的OJ系统经过多年的发展,虽然功能较为完善,但应用于中小学信息技术课堂教学,存在如下问题:①OJ系统用户提交的程序代码在服务器运行,用户较多情况下对服务器的性能有一定要求,需要配置专门的服务器,不符合大多数学校的实际情况。②OJ系统基于B/S架构,通常需要安装数据库和Web服务器并进行必要的配置和部署;OJ系统用户提交的程序代码在执行时有运行时间、内存使用、安全等的限制,需要在服务器上进行配置。使用OJ系统对信息教师的专业能力要求较高。③OJ系统检验的是用户提交程序代码的正确性,其中只有正确和错误两种结果,无法对程序设计填空的正确性进行检验,而目前不少程序设计考题都为填空题,这就需要测评系统具有程序设计填空码的评测功能。以上问题在一定程度上阻碍了OJ系统在中小学信息技术课堂教学中的推广与使用。
要想让广大中小学信息技术教师能够在课堂教学中使用程序测评系统,提升课堂教学的有效性,需要开发一款适用于当下信息技术课堂教学、使用门槛较低的程序测评系统,该系统需要满足如下需求:①系统无需高性能计算机,无需服务器,在机房学生机或者教师机上即可运行使用。②无需部署数据库与Web服务器,无需烦琐复杂的配置。③既能够检验提交的完整代码的正确性,也能够检验程序设计填空的正确性。
● 在线测评系统的设计
笔者根据浙江信息技术教学情况,设计并实现了Python程序设计测评系统——YYOJ系统。该系统有如下优点:①学生提交的程序代码的正确性在学生使用的本地机器上检验,对运行YYOJ系统数据库和Web服务器的计算机性能没有要求,YYOJ系统可以在机房任意一台计算机上运行,不需要配置专门的服务器,也无需对运行YYOJ系统计算机的内存、安全限制进行配置。②YYOJ系统不需要安装数据库和Web服务器并进行配置,它自带数据库和Web服务器的应用程序。③YYOJ系统除了可以检验学生提交的完整程序代码的正确性,还可以检验程序设计填空的正确性。此外,YYOJ系统对硬件设备要求较低,使用门槛不高且易于使用,特别适合浙江高中信息技术课堂教学。
1.系统技术介绍
YYOJ系统是基于B/S架构的Web应用程序,在开发过程中使用了Web框架、Web服务器、数据库等技术。
(1)FastAPI
FastAPI是一个用于构建Web API的现代、高性能的WEB框架,它实现了ASGI规范。虽然FastAPI的主要用途是用于构建Web API,但是FastAPI也提供了对Jinja2、Mako等模板引擎的支持,能够像Flask、Django一样开发基于服务端渲染的Web应用程序。
(2)Uvicorn
Uvicorn是使用C和Python编写的ASGI Web服务器。使用Uvicorn部署实现了ASGI规范的Web应用程序。FastAPI实现了ASGI规范,所以,FastAPI开发的Web应用程序能够部署在Uvicorn中。Uvicorn与传统的Web服务器不同,传统的Web服务器如nginx、apache、IIS需要单独安装,Uvicorn不需要安装,并且可以通过Python编码的方式直接嵌入应用程序中运行。
(3)Nuitka
Nuitka是Python编写的优化Python编译器,它能够把Python代码编译生成为可执行程序,而且通过Nuitka编译生成的可执行程序不需要安装Python环境也能够独立运行。Nuitka支持Python2与Python3,支持Windows、Linux与苹果等主流操作系统。Nuitka的工作原理是把Python代码编译成C代码,再把C代码编译成可执行文件,生成的文件不能像.pyc文件一样反编译,因此安全性高,而且因为编译成C代码,所以生成的可执行程序运行速度会更快。
(4)Brython
Brython是用javascript编写的Python编译器和解析器。使用Brython,可以在浏览器中编译和运行Python代码。
(5)SQLite
SQLite是一个C语言库,它实现了一个小型、快速、自包含、高可靠性、功能齐全的SQL数据库引擎。SQLite内置于所有手机和大多数计算机中,并捆绑在人们每天使用的无数其他应用程序中。SQLite不像MySQL、Postgres那样需要开启服务器提供数据库服务,它是无服务器的数据库,可以通过编程语言调用API直接与SQLite数据库通信。
总的来说,YYOJ系统是使用FastAPI开发的Web应用程序,内嵌了Uvicorn和SQLite,Uvicorn用于承载Web应用程序,SQLite作为应用程序的数据存储,因此,省去了安装数据库和Web服务器以及配置的步骤。YYOJ的源码采用Nuitka编译并生成可执行程序,不需要安装Python环境,使用时把可执行程序拷贝到计算机上直接运行即可。判题代码在浏览器端通过Brython运行检验学生提交程序代码的正确性,提交的程序代码无需上传到服务器后再进行判题,减轻了服务器端的压力。
2.在线测评系统功能设计
YYOJ系统是一个Python程序设计测评系统,教师在系统中录入Python程序设计的题目及其评判代码,学生登录系统根据题目要求编写或完善程序并提交,系统根据教师提供的评判代码对学生提交的程序进行评判,检验学生程序的正确性。YYOJ系统的功能主要包括学生界面功能、教师界面功能、第三方软件实现的管理功能。
(1)学生界面功能
①在线运行。学生可以输入Python代码并运行查看执行结果。该模块输入的Python代码在网页中运行,因此不需要Python编程环境,在浏览器的环境下就可以运行。开发该模块主要是考虑学生如果不在机房或者不在学校,YYOJ系统只要部署在学校的服务器上,学生通过自己的计算机、平板、手机登录YYOJ系统就可以练习Python代码,而无需安装Python编程环境。
②我要挑战。学生可以选择教师录入系统中的题目进行挑战练习,在学生提交Python代码后,系统根据教师的判题代码检验学生提交代码的正确性并反馈结果给学生。学生在课余时间可以使用该模块开展自主编程练习。
③练习反馈。学生登录之后才能使用。在“我要挑战”的基础上还添加了一项额外的功能:学生提交的Python代码检验的结果会保存到数据库中,教师可以在后台查看。
(2)教师界面功能
教师功能必须在教师登录后台之后才能使用,教师功能主要包括以下内容:
①题目查看。对系统中已经录入的题目提供分页查看功能。
②录入题目。提供录入题目的功能。录入的题目包括题目名称、需要批阅的代码、批阅代码三块内容。如果代码完全由学生编写,“需要批阅的代码”留空,如果代码是一部分由学生完善,如程序设计填空,则教师在“需要批阅的代码”中录入无需学生完善的代码部分并标记需要完善的部分。“批阅代码”是检验学生代码正确与否的评判代码。
③修改题目。提供修改录入的某个题目的功能。
④删除题目。提供删除某个题目的功能。
⑤查看做题情况。提供以班级为单位查看某个题目的评判结果的功能。
(3)第三方软件实现的管理功能
①教师管理。提供查看、添加、修改、删除教师账号的功能。
②班级管理。包括班级的查看、添加、修改、删除功能。
③学生管理。包括学生的查看、添加、修改、删除功能。
考虑到YYOJ系统的主要使用群体是信息技术教师,能够使用数据库管理软件来管理数据库中的数据,并且YYOJ使用的是无需服务器的SQLite数据库,所以以上三项功能并未在系统中实现,教师可以直接使用HeidiSQL或者DB Browser for SQLite这样的SQLite数据库管理工具来实现上述功能。
● 在线测评系统的实现
YYOJ系统通过Brython在浏览器中运行评判代码以检验学生提交代码的正确性。当学生点击提交按钮之后,Brython会将学生提交的代码传递给教师编写的评判代码,并在浏览器中运行评判代码检验学生提交的代码是否正确,最后仅将评判的结果返回给服务器并保存在数据库中。因为评判代码在浏览器中运行,所以减轻了服务器的压力。
YYOJ系统与传统的OJ系统不同,YYOJ系统除了支持完整代码正确性的评判,也支持程序设计填空正确性的评判。程序设计填空的答案通常不是唯一的,为了确保评判的正确性,教师需要编写评判代码,通过评判代码来评判程序设计填空的正确性。在学生提交代码之后,教师编写的评判代码在浏览器中运行评判学生提交代码的正确性,并通过AJAX请求将题目的编号、学生标志以及题目正确与否等信息传回服务端并保存在数据库中,教师在后台能够查看学生的答题情况。
评判代码的编写主要分为完整代码的正确性评判和程序设计填空的正确性评判。
1.完整代码的正确性评判
评判完整代码的正确性的方式是检验某些变量的值或者程序的输出在程序运行后是否符合预期。
①根据变量值评判代码正确性。
某些问题会将结果存储到某个变量中,对于这样的问题,需要通过检验变量内存储的值来判断代码的正确性。
例1,描述:在列表s中存储[1, 10]范围内的所有偶数;
题目已有代码:无;
学生提交代码如图1所示。
分析:该问题希望在列表s中存储[1,10]范围内的所有偶数,当程序运行完毕之后,列表s的值为[10,8,6,4,2],要评判提交的代码是否正确,只要判断列表s中是否仅包含2、4、6、8、10这5个偶数即可。
学生提交的代码作为文本字符串存储在变量src中提交给评判代码,评判代码通过exec函数运行学生提交的代码。exec是Python的内置函数,它能够动态地执行存储在字符串或文件中的 Python 语句。
exec(src)
通过上面的语句,学生提交的代码已经在评判代码中运行完毕,在评判代码运行的上下文环境中已经存在变量s且它的值为[10,8,6,4,2]。评判代码只需要判断s的值是否仅包含2、4、6、8、10这5个偶数即可。