代码拉取完成,页面将自动刷新
import os
import re
import shutil
import subprocess
import uuid
from contextlib import suppress
from pathlib import Path
from flask import Flask, request, jsonify
from args import ARGS_BUILDER
BASE_DIR = Path(__file__).parent
CODE_DIR = Path(BASE_DIR, 'code')
DEMO_DIR = Path(BASE_DIR, 'demo')
LANG_SUFFIX = {
'c': '.c',
'cpp': '.cpp',
'java': '.java',
'csharp': '.cs',
'vbscript': '.vb',
'php': '.php',
'python': '.py',
'ruby': '.rb',
'golang': '.go',
'rust': '.rs',
'javascript': '.js',
'typescript': '.ts',
'lua': '.lua',
'kotlin': '.kt'
}
app = Flask(__name__)
@app.get('/')
def index():
""" 首页 """
return app.send_static_file('index.html')
@app.post('/get_code_demo')
def get_demo():
""" 获取演示代码 """
# 获取请求参数
lang = request.form.get('lang')
prev_lang = request.form.get('prev_lang')
prev_code = request.form.get('prev_code')
# 读取示例代码
try:
# 读取上次选择的编程语言对应的示例代码
with open(Path(DEMO_DIR, 'demo' + LANG_SUFFIX.get(prev_lang)), 'r', encoding='UTF-8') as f:
code = f.read()
# 检查示例代码是否被编辑
# 示例代码未被编辑或被清空,则返回当前选择的编程语言对应的示例代码
# 示例代码已被编辑且不为空,则不再返回新的示例代码,以防止覆盖用户编写的代码
prev_code = replace_whitespace(prev_code)
code = replace_whitespace(code)
if not prev_code or code == prev_code:
with open(Path(DEMO_DIR, 'demo' + LANG_SUFFIX.get(lang)), 'r', encoding='UTF-8') as f:
code = f.read()
else:
code = None
except FileNotFoundError:
return jsonify(success=False, message='Failed', code=None)
# 返回示例代码
return jsonify(success=True, message='Succeeded', code=code)
@app.post('/compile')
def compile_code():
""" 编译、执行代码,并返回执行结果 """
# 获取请求参数
code = request.form.get('code')
lang = request.form.get('lang')
stdin = (request.form.get('stdin') or '').replace('\\n', '\n')
# 根据语言类型,构建代码编译和运行的终端命令
args_builder = ARGS_BUILDER.get(lang)
if args_builder is None:
return jsonify({'success': False, 'message': '不支持该语言'})
else:
code_path = Path(CODE_DIR, uuid.uuid4().hex)
try:
compile_args, run_args, compile_filename, source_filename = args_builder(code_path, code)
except Exception as e:
return jsonify({'success': False, 'message': str(e)})
# 保存源代码
save_code(source_filename, code)
# 编译、运行代码,并返回运行结果
try:
if compile_args:
# 编译代码
process = subprocess.Popen(compile_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
try:
output, _ = process.communicate(timeout=30)
except subprocess.TimeoutExpired:
# 编译超时
process.kill()
return jsonify(success=False, message='编译超时')
else:
# 检查是否编译成功
if compile_filename is not None:
if not (compile_filename.is_file() or Path(compile_filename.__str__() + '.exe').is_file()):
return jsonify(success=False, message=f'{decode(output)}')
# 运行代码
# TODO 代码安全性尚未考虑
process = subprocess.Popen(run_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for item in stdin.split('\n'):
# 写入标准输入
process.stdin.write(item.encode('UTF-8') + b'\n')
try:
# 防止程序中的等待输入阻塞程序(也可以接收用户输入)
output, _ = process.communicate(timeout=30)
except subprocess.TimeoutExpired:
# 运行超时
process.kill()
return jsonify(success=False, message='运行超时')
# 返回运行结果
return jsonify(success=True, message=f'{decode(output)}')
except Exception as e:
return jsonify(success=False, message=f'未知错误:{e}')
finally:
with suppress(FileNotFoundError):
shutil.rmtree(code_path)
def save_code(filename, code):
filename = Path(filename)
os.makedirs(filename.parent)
with open(filename, 'w', encoding='UTF-8') as f:
f.write(code)
def decode(data: bytes):
try:
s = data.decode('UTF-8')
except UnicodeDecodeError:
s = data.decode('GBK')
return s
def replace_whitespace(text):
pattern = r'\s' # 正则表达式:匹配任何空白符
replacement = '' # 替换为空字符串
new_text = re.sub(pattern, replacement, text)
return new_text
if __name__ == '__main__':
app.run(host='0.0.0.0')
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。