วันจันทร์ที่ผ่านมาผมนั่งเขียน grader อย่างบ้าคลั่ง เพราะต้องเอามาใช้ตรวจโปรแกรมน้องๆ ในวันอังคาร ผมเขียน grader ด้วยภาษา Python หลายๆคนคงทราบดีว่าโปรแกรม grader เป็นโปรแกรมที่ทำหน้าที่ compile และ run โปรแกรมอื่น เพื่อตรวจสอบว่า input ที่ใส่เข้าไปตรงกับ output ที่ถูกต้องหรือไม่ ถ้าถูกต้องทุก input ก็ถือว่าผ่าน
แต่ว่าโปรแกรมที่เอามาตรวจอาจรันแล้วเกิดอาการติดลูป หรือรันไม่รู้จบ เราจึงต้องกำหนด timeout ว่าให้รันได้ไม่เกินกี่วินาที ถ้าโปรแกรมรันนานเกินไป โปรแกรม grader จะต้องหยุดการทำงาน (End Process) ของโปรแกรมที่ถูกตรวจ
ปรากฏว่าผมไปค้นๆ ในเน็ตก็ไม่เจอตัวอย่างโปรแกรม python ที่สามารถ รันโปรแกรมอื่น แล้วกำหนด timeout แบบง่ายๆ เลย ผมก็เลยพยายามเขียนเอง
ได้โค้ดมาดังนี้ (ใช้ thread และ subprocess)
import subprocess from time import sleep from threading import Thread class process(Thread): # written by Natt Piyapramote <nattster at google mail> # requires: Python 2.6 def __init__(self, filename, input_txt=None): Thread.__init__(self) self.filename = filename self.input_txt = input_txt self.status = 0 self.output = '' def run(self): self.process = subprocess.Popen(self.filename, stdin=subprocess.PIPE, stdout=subprocess.PIPE) self.output, self.err = self.process.communicate(self.input_txt) self.status = 1 def run_process(filename, input_txt=None, timeout=1): "run a process with timeout" p = process(filename, input_txt) p.start() p.join(timeout) if p.status == 0: # process still running? p.process.terminate() while p.isAlive(): sleep(0.1) print 'killing process...' return p.output |
ตัวอย่างการใช้งานฟังก์ชันนี้ก็
run_process('c:\windows\notepad.exe', timeout=4) |
ฟังก์ชัน run_process จะไปเรียกโปรแกรม notepad.exe ให้ทำงาน (ซึ่ง notepad จะรันไปเรื่อยๆ ไม่ปิดตัวเอง) ดังนั้นฟังก์ชัน run_process จะหยุดการทำงานของ notepad ภายในเวลา 4 วินาที
นอกจากนี้ถ้าเรารันโปรแกรมที่เป็น Console Application เราสามารถกำหนด Input ให้กับ Standard Input (stdin) และอ่านค่าจาก Standard Output (stdout) ของโปรแกรมที่รันได้ด้วย (กำหนด Input ให้ตัวแปร input_txt แล้วฟังก์ชันจะคืนค่าข้อความจาก stdout)
อ้อ… ฟังก์ชันนี้ต้องใช้ Python 2.6 นะครับ
เจ๋งดี อิอิ…
ร้ายกาจ^ ^