큐펭스토리
파이썬 강의, 프로그래밍 문제 풀이, 지식 공유 및 정리용
채점 스크립트

학기가 마무리돼 가는 중이다. 띄어쓰기는 참 어렵ㄷ(?)

프로그래밍 과제를 내주고서 학생들로부터 코드를 받는 경우엔 채점 자체가 어렵다. 학문적으로 어렵다기 보다는 시간이 오래 걸리는 작업이 된다. 차라리 그 시간에 나보고 그 숙제를 하라고 하면 두 번은 할 것 같다. 전산 학문의 좋은 점은 이럴 때 자동화 시스템을 만들 수 있다는 점이다. 나~중에 NLP가 발전하면 일반적인 report에 대해서도 자동 채점 프로그램을 만들 수 있겠지? 지금 단순히 turnitin 같은 데서 originality check에서 그치는 정도가 아니겠지?


무튼 그래서 이번 시간에는 내가 만든 자동 채점 스크립트에 대해 얘기할 것이다.




자동 채점 스크립트.


사실 학생들이 조금만 도와주면(?) 혹은 코드 제출 당시에 조금만 필터링 해준다면(?) 좀 더 쉽게 프로그램을 짤 수도 있을 것이다. 채점할 파일이 정확한 포맷을 지켜서 제출된다면 채점 프로그램이 이들을 자동으로 평가하기 편하게 된다. 더 나아가서 컴파일 에러가 없는 코드만 낼 수 있다거나, 무한 루프나 에러가 없는 코드 등등의 문제를 해결할 수도 있을 것이다. 현실은 그렇지 못하다. 오히려 각각의 에러는 학생들 코드를 평가하는 지표로 쓰인다. 내 프로그램이 망가지면(?) 어쨌든 문제는 발생한거고, 그만큼 학생들의 점수는 감점될 것이다.






위 사진은 채점을 시작할 폴더(디렉토리)의 모습이다.

채점은 grade.sh가 할 것이다.

testcase 폴더에는 각각의 input_*.txt 에 대응되는 정답 output_*.txt가 존재한다.

학생들 코드를 적절하게 테스트할 10개의 테스트 파일들이다.

학생들 코드는 PA2_201????? 폴더 안에 PA2_201?????.py 파일로 존재한다.

즉 채점 스크립트는 각 폴더를 순회하면서 input들을 집어넣고 생성되는 파일들을 가지고서 output과 비교하면 된다.


만약 학생들 코드들의 templete을 제공해서 input과 output을 내놓는 포맷을 미리 지정해놨다면 채점이 편해진다.

*.py를 input과 실행하는 방법이라거나 output파일 이름 규칙을 미리 정해주는 식이다.

예를 들어서, $ python PA2_20170001.py input_1.txt 를 실행하면 같은 폴더에 output_1.txt가 생성되는 것이다.

물론 지키지 않는 학생들이 있을테니 그만큼 불쾌지수(?)는 올라갈것이다 ㅎㅎㅎㅎㅎㅎㅎ





grade.sh에 대해 좀 더 알아보자. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/sh
 
testcase=10
for std_id in 20170001 20170002 20170003 ...
do
    echo "std_id is ${std_id} yes"
    cd PA2_${std_id}
    counter=0
    while [ "$counter" -lt ${testcase} ]
    do
        ((counter++))
        rm output_${counter}.txt
        python PA2_${std_id}.py input_${counter}.txt;
        diff output_${counter}.txt ../testcase/output_${counter}.txt -sq
    done
    cd ".."
done
cs


위와 같은 shell program으로 돼있다.

아 참고로 이건 MAC에서 짠거다. rm, diff가 windows cmd에선 동작 안할테니까 안될거다.

나도 shell은 처음 써봤다. 역사로 보면 당연히 파이썬보다 먼저 만들어졌으니 파이썬이 쉘을 닮은 부분이 많다고 표현하는게 맞겠지만 나는 파이썬을 먼저 배웠으니까 쉘을 쓰면서 for, do, while, 등을 보면서 좀 놀랬다 ㅋㅋㅋ


몇가지 살펴보자면, 3줄, 8줄과 같이 변수를 선언할때는 이름과 = 사이에 빈공간이 있으면 안된다. 그런게 있다면 cd, rm, python, diff처럼 명령어로 받아들인다.

4줄의 for __ in ... 에서 ... 구간에 좀 전의 폴더들을 참고해서 학번과 같은 규칙성 단어들을 적으면 된다.

좀 더 자동화시키려면 ls, grep, awk 등을 활용하면 되지 않을까? 디렉토리 안의 하위 폴더들이나 파일들을 검색하는 식이로... 이건 담에 하기로 하고 ㅇㅇ;


무튼 저 for를 순회하면서 7줄을 통해 해당 폴더로 진입하고 16줄에서 되돌아나온다.


변수 counter를 0으로 초기화시켜주고서 while로 들어선다.

while안에서 counter는 testcase변수보다 작은 동안 (-lt, lessthan) 반복한다.

들어서자마자 counter는 1 증가된다. ( ++ )

존재하는 output_*.txt를 지우고서 13줄을 통해 학생 코드를 실행시킨다.

이후에 생성된 output과 상위 폴더의 testcase 폴더 안의 output을 비교해서 적절한 반응을 화면에 보여준다.

diff -sq는 입력된 파일들에 따라 *** and ??? are identical 혹은 *** and ??? differ를 출력한다.


이렇게 실행시키고서 출력된 결과에 따라 채점 기록 파일에 기록하면된다.

만약 python으로 이걸 짜게 될 경우, 14 줄의 결과에 따라 .csv 파일에 결과를 기록하는 식으로 좀 더 자동화할 수 있을 것이다. 




아쉬움이 많이 남지만...거의 한 달 동안 글을 안 쓴 죄로 이거라도 써야겠다는 맘에 남긴다.

각 명령어들을 모르는 사람이 읽기엔 딱히 좋은 글이 아닌 것 같다.

설명이 많이 성의없어 보이긴 한다 ㅜㅜㅜ




  Comment ,     Trackback