Khi code C++ mỗi lần test chúng ta cần nhập thủ công input và output, chúng ta cũng không biết thời gian chạy của code là bao nhiêu do vậy chúng ta sẽ xây dựng một công cụ bằng python giúp ta tự động làm việc này.
Về cơ bản chúng ta sẽ sử dụng python để chạy một số lệnh như mình chạy trong cmd vd như:
Compile C++:
g++ code.cpp -o tmp.exe
Run:
tmp.exe < input.txt > output.txt
Bắt đầu code python:
import os
import time
import subprocess
t = time.time()
subprocess.run(['g++','code.cpp','-o','tmp.exe'])
os.system("tmp.exe < input.txt > tmp.txt")
print(time.time()-t)
f = open('output.txt','r').read().strip();
tmp = open('tmp.txt','r').read().strip();
if(f==tmp):
print("OK")
else:
print("WA")
Đoạn code trên là chương trình python đơn giản để thực hiện việc chạy file c++.
time.time()
Lấy thời gian hiện tại
subprocess.run(['g++','code.cpp','-o','tmp.exe'])
Chạy một lệch cmd
như chương trình con.
os.system("tmp.exe < input.txt > tmp.txt")
chạy một lệnh cmd
nhưng yêu cầu hệ điều hành chạy
=> chúng ta sẽ tìm hiểu sau về chúng.
Đoạn code trên cơ bản đã đáp ứng được nhưng vấn đề gặp phải là biên dịch lỗi, chạy quá thời gian thì chưa làm được. Bây giờ hãy cập nhật đoạn mã trên lên 1 level mới.
import os
import time
import subprocess
import compare
compileTimeout = 5
runTimeout = 5
compare.formatInput('input.txt')
compare.formatInput('dest.txt')
compileProc = subprocess.run(
['g++', 'code.cpp', '-o', 'tmp.exe'], timeout=compileTimeout, capture_output=True)
err = compileProc.stderr
if err != b'':
print("Compile ERROR", err.decode())
else:
try:
t = time.time()
runProc = subprocess.Popen(
args=["tmp.exe"], stdout=subprocess.PIPE, stdin=subprocess.PIPE)
grep_stdout = runProc.communicate(
input=open('input.txt', 'rb').read(), timeout=runTimeout)[0]
print(grep_stdout.decode())
with open("output.txt", 'w', encoding='utf-8', newline='\n') as f:
f.write(grep_stdout.decode())
print("RUN TIME: ", (time.time()-t))
compare.compareFile('output.txt', 'dest.txt')
except Exception:
print("TLE")
runProc.kill()
compare
là file để fomat lại input. Mình sẽ để trong github ở dưới.
subprocess.run
Như đã giới thiệu ở trên thì thằng này sẽ chạy 1 chương trình con ngay trong chương trình chính.
- Tham số đầu tiên là mảng lệnh
['g++', 'code.cpp', '-o', 'tmp.exe']
timeout
Khi quá thời gian này thì subprocess bị dừng. Tính bằng giây
subprocess.Popen
Thằng này cũng như subprocess.run
nhưng điểm khác là nó có thể tương tác trong quá trình chạy.
grep_stdout = runProc.communicate(input=open('input.txt', 'rb').read(), timeout=runTimeout)[0]
sử dung communicate
để truyền input vào và nhận output ra. Dữ liệu vào ở dạng binary.
Như vậy chúng ta đã xây dựng được công cụ tự động chạy code c++.
repo: https://github.com/npv2k1/CTDLvaGT/tree/master/tool
Một số tài liệu tham khảo: