Python在线编辑器

news2025/2/3 5:16:18

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) 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2291101.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ZZNUOJ(C/C++)基础练习1041——1050(详解版)

1041 : 数列求和2 题目描述 输入一个整数n&#xff0c;输出数列1-1/31/5-……前n项的和。 输入 输入只有一个整数n。 输出 结果保留2为小数,单独占一行。 样例输入 3 样例输出 0.87注意sum 1相当于sumsum1 注意sum * 1相当于sumsum*1 C语言版 #include<stdio.h> // 包含…

浅析DDOS攻击及防御策略

DDoS&#xff08;分布式拒绝服务&#xff09;攻击是一种通过大量计算机或网络僵尸主机对目标服务器发起大量无效或高流量请求&#xff0c;耗尽其资源&#xff0c;从而导致服务中断的网络攻击方式。这种攻击方式利用了分布式系统的特性&#xff0c;使攻击规模更大、影响范围更广…

深度学习 Pytorch 神经网络的学习

本节将从梯度下降法向外拓展&#xff0c;介绍更常用的优化算法&#xff0c;实现神经网络的学习和迭代。在本节课结束将完整实现一个神经网络训练的全流程。 对于像神经网络这样的复杂模型&#xff0c;可能会有数百个 w w w的存在&#xff0c;同时如果我们使用的是像交叉熵这样…

【回溯】目标和 字母大小全排列

文章目录 494. 目标和解题思路&#xff1a;回溯784. 字母大小写全排列解题思路&#xff1a;回溯 494. 目标和 494. 目标和 给你一个非负整数数组 nums 和一个整数 target 。 向数组中的每个整数前添加 或 - &#xff0c;然后串联起所有整数&#xff0c;可以构造一个 表达式…

Linux系统上安装与配置 MySQL( CentOS 7 )

目录 1. 下载并安装 MySQL 官方 Yum Repository 2. 启动 MySQL 并查看运行状态 3. 找到 root 用户的初始密码 4. 修改 root 用户密码 5. 设置允许远程登录 6. 在云服务器配置 MySQL 端口 7. 关闭防火墙 8. 解决密码错误的问题 前言 在 Linux 服务器上安装并配置 MySQL …

记录一次,PyQT的报错,多线程Udp失效,使用工具如netstat来检查端口使用情况。

1.问题 报错Exception in thread Thread-1: Traceback (most recent call last): File "threading.py", line 932, in _bootstrap_inner File "threading.py", line 870, in run File "main.py", line 456, in udp_recv IndexError: list…

群晖NAS安卓Calibre 个人图书馆

docker 下载镜像johngong/calibre-web&#xff0c;安装之 我是本地的/docker/xxx/metadata目录 映射到 /usr/local/calibre-web/app/cps/metadata_provider CALIBREDB_OTHER_OPTION 删除 CALIBRE_SERVER_USER calibre_server_user 缺省用户名口令 admin admin123 另外有个N…

android主题设置为..DarkActionBar.Bridge时自定义DatePicker选中日期颜色

安卓自定义DatePicker选中日期颜色 背景&#xff1a;解决方案&#xff1a;方案一&#xff1a;方案二&#xff1a;实践效果&#xff1a; 背景&#xff1a; 最近在尝试用原生安卓实现仿element-ui表单校验功能&#xff0c;其中的的选择日期涉及到安卓DatePicker组件的使用&#…

彩色控制台,自动换行...学习个新概念:流操控器![more cpp--11]

孩子们&#xff0c;我回来了。先看看今天我又学了什么CPP的没啥用新特性。彩色的控制台&#xff01; 还有很多的新花样&#xff01; 事情要从去年八月讲起&#xff0c;我那个时候在研究流函数&#xff0c;写了一些比较愚笨的代码。 为什么要研究这个呢&#xff1f;虽然我们的C…

基于单片机的盲人智能水杯系统(论文+源码)

1 总体方案设计 本次基于单片机的盲人智能水杯设计&#xff0c;采用的是DS18B20实现杯中水温的检测&#xff0c;采用HX711及应力片实现杯中水里的检测&#xff0c;采用DS1302实现时钟计时功能&#xff0c;采用TTS语音模块实现语音播报的功能&#xff0c;并结合STC89C52单片机作…

TensorFlow 示例摄氏度到华氏度的转换(一)

TensorFlow 实现神经网络模型来进行摄氏度到华氏度的转换&#xff0c;可以将其作为一个回归问题来处理。我们可以通过神经网络来拟合这个简单的转换公式。 1. 数据准备与预处理 2. 构建模型 3. 编译模型 4. 训练模型 5. 评估模型 6. 模型应用与预测 7. 保存与加载模型 …

win10部署本地deepseek-r1,chatbox,deepseek联网(谷歌网页插件Page Assist)

win10部署本地deepseek-r1&#xff0c;chatbox&#xff0c;deepseek联网&#xff08;谷歌网页插件Page Assist&#xff09; 前言一、本地部署DeepSeek-r1step1 安装ollamastep2 下载deepseek-r1step2.1 找到模型deepseek-r1step2.2 cmd里粘贴 后按回车&#xff0c;进行下载 ste…

【memgpt】letta 课程6: 多agent编排

Lab 6: Multi-Agent Orchestration 多代理协作 letta 是作为一个服务存在的,app通过restful api 通信 多智能体之间如何协调与沟通? 相互发送消息共享内存块,让代理同步到不同的服务的内存块

Java 大视界 -- Java 大数据在自动驾驶中的数据处理与决策支持(68)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

【Linux】opencv在arm64上提示找不到libjasper-dev

解决opencv在arm64上提示找不到libjasper-dev的问题。 本文首发于❄慕雪的寒舍 问题说明 最近我在尝试编译opencv&#xff0c;安装依赖项libjasper1和libjasper-dev的时候就遇到了这个问题。在amd64平台上&#xff0c;我们可以通过下面的命令安装&#xff08;ubuntu18.04&…

LabVIEW在电机自动化生产线中的实时数据采集与生产过程监控

在电机自动化生产线中&#xff0c;实时数据采集与生产过程监控是确保生产效率和产品质量的重要环节。LabVIEW作为一种强大的图形化编程平台&#xff0c;可以有效实现数据采集、实时监控和自动化控制。详细探讨如何利用LabVIEW实现这一目标&#xff0c;包括硬件选择、软件架构设…

Baklib揭示内容中台与人工智能技术的创新协同效应

内容概要 在当今信息爆炸的时代&#xff0c;内容的高效生产与分发已成为各行业竞争的关键。内容中台与人工智能技术的结合&#xff0c;为企业提供了一种新颖的解决方案&#xff0c;使得内容创造的流程更加智能化和高效化。 内容中台作为信息流动的核心&#xff0c;能够集中管…

18.Word:数据库培训课程❗【34】

目录 题目 NO1.2.3.4 NO5设置文档内容的格式与样式 NO6 NO7 NO8.9 NO10.11标签邮件合并 题目 NO1.2.3.4 FnF12&#xff1a;打开"Word素材.docx”文件,将其另存为"Word.docx”在考生文件夹下之后到任务9的所有操作均基于此文件&#xff1a;"Word.docx”…

git多人协作

目录 一、项目克隆 二、 1、进入克隆仓库设置 2、协作处理 3、冲突处理 4、多人协作分支的推送拉取删除 1、分支推送&#xff08;2种&#xff09; 2、远程分支拉取&#xff08;2种&#xff09; 3、远程分支删除 一、项目克隆 git clone 画船听雨眠/test1 (自定义的名…

什么是线性化PDF?

线性化PDF是一种特殊的PDF文件组织方式。 总体而言&#xff0c;PDF是一种极为优雅且设计精良的格式。PDF由大量PDF对象构成&#xff0c;这些对象用于创建页面。相关信息存储在一棵二叉树中&#xff0c;该二叉树同时记录文件中每个对象的位置。因此&#xff0c;打开文件时只需加…