ใช้ python เรียกโปรแกรมอื่น โดยมี timeout

วันจันทร์ที่ผ่านมาผมนั่งเขียน 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 
    # 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:windowsnotepad.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 นะครับ

2 คิดบน “ใช้ python เรียกโปรแกรมอื่น โดยมี timeout

ใส่ความเห็น

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / เปลี่ยนแปลง )

Twitter picture

You are commenting using your Twitter account. Log Out / เปลี่ยนแปลง )

Facebook photo

You are commenting using your Facebook account. Log Out / เปลี่ยนแปลง )

Google+ photo

You are commenting using your Google+ account. Log Out / เปลี่ยนแปลง )

Connecting to %s