使用Python開發(fā)在線編輯器
更新時間:2025年02月05日 10:19:35 作者:mosquito_lover1
這篇文章主要為大家詳細介紹了如何使用Python開發(fā)一個在線編輯器,文中的示例代碼講解詳細,具有一定的借鑒價值,有需要的小伙伴可以了解一下
實現(xiàn)效果

完整代碼
from flask import Flask, render_template, request, jsonify
import sys
from io import StringIO
import contextlib
import subprocess
import importlib
import threading
import time
import ast
import re
app = Flask(__name__)
RESTRICTED_PACKAGES = {
'tkinter': '抱歉,在線編譯器不支持 tkinter,因為它需要圖形界面環(huán)境。請在本地運行需要GUI的代碼。',
'tk': '抱歉,在線編譯器不支持 tk/tkinter,因為它需要圖形界面環(huán)境。請在本地運行需要GUI的代碼。',
'pygame': 'pygame將被轉(zhuǎn)換為Web版本運行' # 不再限制pygame,而是轉(zhuǎn)換它
}
def convert_tkinter_to_web(code):
"""將tkinter代碼轉(zhuǎn)換為Web等效實現(xiàn)"""
# 解析Python代碼
tree = ast.parse(code)
# 提取窗口屬性
window_props = {
'title': 'Python GUI',
'width': '700',
'height': '500',
'buttons': [],
'labels': [],
'entries': [],
'layout': []
}
# 用于存儲函數(shù)定義
functions = {}
# 首先收集所有函數(shù)定義
for node in ast.walk(tree):
if isinstance(node, ast.FunctionDef):
functions[node.name] = ast.unparse(node)
# 分析代碼中的tkinter組件
for node in ast.walk(tree):
if isinstance(node, ast.Assign):
if isinstance(node.value, ast.Call):
# 提取窗口標題
if hasattr(node.value.func, 'attr') and node.value.func.attr == 'Tk':
for subnode in ast.walk(tree):
if isinstance(subnode, ast.Call) and hasattr(subnode.func, 'attr'):
if subnode.func.attr == 'title' and len(subnode.args) > 0:
window_props['title'] = ast.literal_eval(subnode.args[0])
elif subnode.func.attr == 'geometry' and len(subnode.args) > 0:
geom = ast.literal_eval(subnode.args[0])
match = re.match(r'(\d+)x(\d+)', geom)
if match:
window_props['width'] = match.group(1)
window_props['height'] = match.group(2)
# 提取按鈕
elif hasattr(node.value.func, 'attr') and node.value.func.attr == 'Button':
button = {'text': 'Button', 'command': None}
for kw in node.value.keywords:
if kw.arg == 'text':
button['text'] = ast.literal_eval(kw.value)
elif kw.arg == 'command':
# 處理不同類型的command
if isinstance(kw.value, ast.Name):
# 簡單的函數(shù)名
button['command'] = kw.value.id
elif isinstance(kw.value, ast.Lambda):
# Lambda表達式
button['command'] = f"lambda_{len(window_props['buttons'])}"
functions[button['command']] = ast.unparse(kw.value)
else:
# 其他情況,嘗試轉(zhuǎn)換為字符串
try:
button['command'] = ast.unparse(kw.value)
except:
button['command'] = 'unknown_command'
window_props['buttons'].append(button)
# 提取標簽
elif hasattr(node.value.func, 'attr') and node.value.func.attr == 'Label':
label = {'text': ''}
for kw in node.value.keywords:
if kw.arg == 'text':
try:
label['text'] = ast.literal_eval(kw.value)
except:
# 如果不是字面量,嘗試直接轉(zhuǎn)換為字符串
label['text'] = ast.unparse(kw.value)
window_props['labels'].append(label)
# 提取輸入框
elif hasattr(node.value.func, 'attr') and node.value.func.attr == 'Entry':
try:
entry_id = node.targets[0].id
except:
entry_id = f"entry_{len(window_props['entries'])}"
window_props['entries'].append({'id': entry_id})
# 生成Web等效代碼
web_code = f"""
<!DOCTYPE html>
<div class="tk-window" style="width: {window_props['width']}px; height: {window_props['height']}px;">
<div class="tk-title-bar">{window_props['title']}</div>
<div class="tk-content">
"""
# 添加標簽
for label in window_props['labels']:
web_code += f' <div class="tk-label">{label["text"]}</div>\n'
# 添加輸入框
for entry in window_props['entries']:
web_code += f' <input type="text" class="tk-entry" id="{entry["id"]}">\n'
# 添加按鈕
for button in window_props['buttons']:
command = button['command'] if button['command'] else ''
web_code += f' <button class="tk-button" onclick="tkButtonClick(\'{command}\')">{button["text"]}</button>\n'
web_code += """ </div>
</div>
<script>
window.pythonFunctions = {
"""
# 添加Python函數(shù)定義
for func_name, func_code in functions.items():
web_code += f" '{func_name}': {func_code},\n"
web_code += """};
</script>
"""
return web_code
def convert_pygame_to_web(code):
"""將pygame代碼轉(zhuǎn)換為Web Canvas實現(xiàn)"""
web_code = """
<canvas id="pygame-canvas" style="border: 1px solid #000;"></canvas>
<script>
const canvas = document.getElementById('pygame-canvas');
const ctx = canvas.getContext('2d');
// 設(shè)置畫布大小
canvas.width = 800;
canvas.height = 600;
// 模擬 pygame 的基本功能
const pygame = {
display: {
set_mode: (size) => {
canvas.width = size[0];
canvas.height = size[1];
return canvas;
},
update: () => {
// Canvas 自動更新
},
flip: () => {
// Canvas 自動更新
}
},
draw: {
rect: (surface, color, rect) => {
ctx.fillStyle = `rgb(${color[0]},${color[1]},${color[2]})`;
ctx.fillRect(rect[0], rect[1], rect[2], rect[3]);
},
circle: (surface, color, pos, radius) => {
ctx.beginPath();
ctx.fillStyle = `rgb(${color[0]},${color[1]},${color[2]})`;
ctx.arc(pos[0], pos[1], radius, 0, Math.PI * 2);
ctx.fill();
}
},
event: {
get: () => [], // 簡化的事件處理
pump: () => {}
},
init: () => {},
quit: () => {},
time: {
Clock: function() {
return {
tick: (fps) => 1000/fps
};
}
}
};
// 轉(zhuǎn)換后的Python代碼
function runGame() {
try {
// 這里將插入轉(zhuǎn)換后的游戲代碼
%PYTHON_CODE%
} catch (error) {
console.error('Game error:', error);
}
}
// 啟動游戲循環(huán)
runGame();
</script>
"""
# 處理 Python 代碼
try:
tree = ast.parse(code)
# 轉(zhuǎn)換 Python 代碼為 JavaScript
js_code = convert_pygame_code_to_js(tree)
web_code = web_code.replace('%PYTHON_CODE%', js_code)
return web_code
except Exception as e:
return f"<div class='error'>轉(zhuǎn)換錯誤: {str(e)}</div>"
def convert_pygame_code_to_js(tree):
"""將 Python AST 轉(zhuǎn)換為 JavaScript 代碼"""
js_code = []
for node in ast.walk(tree):
if isinstance(node, ast.Import):
continue # 跳過導(dǎo)入語句
elif isinstance(node, ast.Assign):
# 轉(zhuǎn)換賦值語句
if hasattr(node.value, 'func') and isinstance(node.value.func, ast.Attribute):
if node.value.func.attr == 'set_mode':
js_code.append(f"const screen = pygame.display.set_mode([{node.value.args[0].elts[0].n}, {node.value.args[0].elts[1].n}]);")
elif isinstance(node, ast.While):
# 轉(zhuǎn)換游戲主循環(huán)
js_code.append("function gameLoop() {")
# ... 處理循環(huán)體
js_code.append(" requestAnimationFrame(gameLoop);")
js_code.append("}")
js_code.append("gameLoop();")
return "\n".join(js_code)
def install_package(package):
"""自動安裝缺失的包"""
# 檢查是否是受限制的包
if package.lower() in RESTRICTED_PACKAGES:
raise ImportError(RESTRICTED_PACKAGES[package.lower()])
try:
importlib.import_module(package)
except ImportError:
try:
# 嘗試使用 pip 安裝包
subprocess.check_call([sys.executable, "-m", "pip", "install", package])
except subprocess.CalledProcessError as e:
raise Exception(f"安裝包 {package} 失敗: {str(e)}")
def timeout_handler():
"""強制終止超時的代碼執(zhí)行"""
raise TimeoutError("代碼執(zhí)行超時(最大執(zhí)行時間:5秒)")
@app.route('/')
def index():
return render_template('index.html')
@app.route('/execute', methods=['POST'])
def execute_code():
code = request.json.get('code', '')
try:
# 檢測是否包含pygame代碼
if 'pygame' in code:
web_code = convert_pygame_to_web(code)
return jsonify({
'status': 'success',
'output': '',
'gui': web_code
})
# 檢測是否包含tkinter代碼
elif 'tkinter' in code or 'tk' in code:
web_code = convert_tkinter_to_web(code)
return jsonify({
'status': 'success',
'output': '',
'gui': web_code
})
# 非GUI代碼正常執(zhí)行
output_buffer = StringIO()
with contextlib.redirect_stdout(output_buffer):
exec(code, globals(), {})
output = output_buffer.getvalue()
return jsonify({
'status': 'success',
'output': output if output else '程序執(zhí)行完成,沒有輸出'
})
except Exception as e:
return jsonify({
'status': 'error',
'output': f'錯誤: {str(e)}'
})
if __name__ == '__main__':
app.run(debug=True) 以上就是使用Python開發(fā)在線編輯器的詳細內(nèi)容,更多關(guān)于Python在線編輯器的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
gethostbyaddr在Python3中引發(fā)UnicodeDecodeError
本文介紹了gethostbyaddr()在Python?3中引發(fā)UnicodeDecodeError的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-05-05
python爬取Ajax動態(tài)加載網(wǎng)頁過程解析
這篇文章主要介紹了python爬取Ajax動態(tài)加載網(wǎng)頁過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-09-09
在交互式環(huán)境中執(zhí)行Python程序過程詳解
這篇文章主要介紹了在交互式環(huán)境中執(zhí)行Python程序過程詳解,運行Python腳本程序的方式有多種,目前主要的方式有:交互式環(huán)境運行、命令行窗口運行、開發(fā)工具上運行等,其中在不同的操作平臺上還互不相同,需要的朋友可以參考下2019-07-07
學(xué)python需要去培訓(xùn)機構(gòu)嗎
在本篇文章里小編給大家整理的是關(guān)于學(xué)python是否需要去培訓(xùn)機構(gòu)的相關(guān)內(nèi)容,有需要的朋友們可以閱讀下。2020-07-07
詳解pyqt中解決國際化tr()函數(shù)不起作用的問題
本文主要介紹了pyqt中解決國際化tr()函數(shù)不起作用的問題,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02
Python虛擬環(huán)境管理工具virtualenv詳解
在Python開發(fā)過程中,我們常常需要管理不同項目的依賴,每個項目可能依賴不同版本的Python庫,因此,如何有效管理這些庫成為了開發(fā)者日常工作中不可忽視的問題,需要的朋友可以參考下2024-12-12

