当前位置: 代码网 > it编程>前端脚本>Python > 使用Python开发在线编辑器

使用Python开发在线编辑器

2025年02月13日 Python 我要评论
实现效果完整代码from flask import flask, render_template, request, jsonifyimport sysfrom io import stringioi

实现效果

完整代码

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,因为它需要图形界面环境。请在本地运行需要gui的代码。',
    'tk': '抱歉,在线编译器不支持 tk/tkinter,因为它需要图形界面环境。请在本地运行需要gui的代码。',
    'pygame': 'pygame将被转换为web版本运行'  # 不再限制pygame,而是转换它
}
 
def convert_tkinter_to_web(code):
    """将tkinter代码转换为web等效实现"""
    # 解析python代码
    tree = ast.parse(code)
    
    # 提取窗口属性
    window_props = {
        'title': 'python gui',
        'width': '700',
        'height': '500',
        'buttons': [],
        'labels': [],
        'entries': [],
        'layout': []
    }
    
    # 用于存储函数定义
    functions = {}
    
    # 首先收集所有函数定义
    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):
                                # 简单的函数名
                                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:
                                # 其他情况,尝试转换为字符串
                                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:
                                # 如果不是字面量,尝试直接转换为字符串
                                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函数定义
    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代码转换为web canvas实现"""
    web_code = """
<canvas id="pygame-canvas" style="border: 1px solid #000;"></canvas>
<script>
const canvas = document.getelementbyid('pygame-canvas');
const ctx = canvas.getcontext('2d');
// 设置画布大小
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
            };
        }
    }
};
// 转换后的python代码
function rungame() {
    try {
        // 这里将插入转换后的游戏代码
        %python_code%
    } catch (error) {
        console.error('game error:', error);
    }
}
// 启动游戏循环
rungame();
</script>
"""
    
    # 处理 python 代码
    try:
        tree = ast.parse(code)
        # 转换 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'>转换错误: {str(e)}</div>"
 
def convert_pygame_code_to_js(tree):
    """将 python ast 转换为 javascript 代码"""
    js_code = []
    
    for node in ast.walk(tree):
        if isinstance(node, ast.import):
            continue  # 跳过导入语句
        elif isinstance(node, ast.assign):
            # 转换赋值语句
            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):
            # 转换游戏主循环
            js_code.append("function gameloop() {")
            # ... 处理循环体
            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():
    """强制终止超时的代码执行"""
    raise timeouterror("代码执行超时(最大执行时间: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代码正常执行
        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 '程序执行完成,没有输出'
        })
        
    except exception as e:
        return jsonify({
            'status': 'error',
            'output': f'错误: {str(e)}'
        })
 
if __name__ == '__main__':
    app.run(debug=true) 

以上就是使用python开发在线编辑器的详细内容,更多关于python在线编辑器的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com