为了初学者验证一些简单的python代码,写了一个小程序,能在线运行一些基础的python代码,还给了一些例子,后续会新增更多用例。
简单首页
后续更新其他基础知识
在线编程页面里主要是一个输入框,和一些代码例子,点击即可自动导入,点击运行代码后, 后端会执行相应运行。
运行结果页面里,有详细的运行print打印结果 和 运行代码,可一键复制
后端核心代码如下:
import io
import sys
from flask import g
import random
from common.dbTools.paging import easy_paging
from models.code import XExampleCode
from common.resMsg import ok_res
def run():
data = g.jm
code_str = data.get('code')
res = capture_print_output(code_str)
res_data = {
'code': code_str,
'res': res
}
return ok_res(res_data)
def capture_print_output(code_str):
# 创建一个StringIO对象来捕获输出
captured_output = io.StringIO()
# 将标准输出重定向到StringIO对象
sys.stdout = captured_output
try:
# 执行传入的Python代码
exec(code_str)
except Exception as e:
return [f"Error: {str(e)}"]
finally:
# 恢复标准输出
sys.stdout = sys.__stdout__
# 返回捕获的输出并按行分割成列表
return captured_output.getvalue().splitlines()
代码详细解释
由chatGPT协助整理
这个代码实现了一个通过 Flask 路由执行动态传入 Python 代码的功能,并捕获其中的 print
输出。以下是对代码的逐步解析。
1. 导入模块
import io
import sys
from flask import g
import random
from common.dbTools.paging import easy_paging
from models.code import XExampleCode
from common.resMsg import ok_res
io
:用于处理文本流,包括字符串流。这里用它来捕获标准输出(stdout
)。sys
:提供访问和修改 Python 解释器的接口。这里用来重定向标准输出。flask.g
:Flask 中的全局变量g
,用于存储当前请求的上下文数据。在此代码中,它用来获取请求数据g.jm
。random
:标准 Python 库,用于生成随机数(虽然在当前代码中没有用到)。easy_paging
:自定义的分页工具模块,可能是用于实现分页功能的工具函数(当前代码中没有使用)。XExampleCode
:假设是你定义的模型类(此代码中未使用,但可能在其他地方使用)。ok_res
:从common.resMsg
模块导入的函数,显然是一个标准的返回响应函数,用来封装返回的结果。
2. run
函数:接收输入代码并返回执行结果
def run():
data = g.jm # 获取请求上下文中的 'jm' 数据
code_str = data.get('code') # 从数据中获取 'code' 字段,即用户传入的代码
res = capture_print_output(code_str) # 执行代码并捕获输出
res_data = {
'code': code_str, # 返回的结果中包含原始代码
'res': res # 返回的结果中包含代码执行的输出
}
return ok_res(res_data) # 使用 ok_res 函数返回结果
解释:
data = g.jm
:获取 Flask 请求上下文中的g.jm
数据。这通常是前端发送的 JSON 数据,包含了用户提交的代码字符串。code_str = data.get('code')
:从data
中获取code
字段,即用户传递的 Python 代码字符串。res = capture_print_output(code_str)
:调用capture_print_output
函数来执行这段 Python 代码,并捕获其中的print
输出。res_data
:构建一个字典,包含了原始的代码和执行结果。返回的结果中会包含这两部分。return ok_res(res_data)
:调用ok_res
函数返回成功响应,res_data
作为响应数据传递。
3. capture_print_output
函数:捕获 print
输出
def capture_print_output(code_str):
# 创建一个StringIO对象来捕获输出
captured_output = io.StringIO()
# 将标准输出重定向到StringIO对象
sys.stdout = captured_output
try:
# 执行传入的Python代码
exec(code_str)
except Exception as e:
return [f"Error: {str(e)}"] # 捕获异常并返回错误信息
finally:
# 恢复标准输出
sys.stdout = sys.__stdout__
# 返回捕获的输出并按行分割成列表
return captured_output.getvalue().splitlines()
解释:
-
captured_output = io.StringIO()
:- 创建一个
StringIO
对象,它模拟一个内存中的文件流,能够捕获并存储print
输出。
- 创建一个
-
sys.stdout = captured_output
:- 将 Python 的标准输出
sys.stdout
重定向到captured_output
。这样,所有的print
语句输出的内容都会被捕获到captured_output
中,而不会显示在控制台。
- 将 Python 的标准输出
-
exec(code_str)
:- 使用
exec
函数动态执行传入的 Python 代码code_str
。这可以执行任意的 Python 代码,适用于动态的场景(如在 Web 应用中执行用户传入的代码)。
- 使用
-
except Exception as e
:- 如果在执行过程中发生错误,会进入
except
块,将错误信息以列表形式返回。这可以帮助开发者捕获并显示执行错误。
- 如果在执行过程中发生错误,会进入
-
finally: sys.stdout = sys.__stdout__
:- 无论执行是否成功,都会执行
finally
块,恢复sys.stdout
为默认的标准输出,避免影响后续的print
输出。
- 无论执行是否成功,都会执行
-
captured_output.getvalue().splitlines()
:- 使用
captured_output.getvalue()
获取捕获到的所有输出,返回一个字符串。 - 然后使用
splitlines()
将输出按行分割成一个列表,每一行是一个print
输出的内容。
- 使用
4. 最终结果
假设你向 Flask 路由传递了以下代码:
{
"code": "print('Hello, World!')"
}
在调用 run()
方法时,Flask 会执行 capture_print_output
,其中:
exec(code_str)
执行print('Hello, World!')
。print
输出被捕获并存储在captured_output
中。- 最终返回的结果可能是:
{
"code": "print('Hello, World!')",
"res": ["Hello, World!"]
}
如果代码中存在错误,例如:
{
"code": "print('Hello World!'"
}
执行时会抛出 SyntaxError
,并返回错误信息:
{
"code": "print('Hello World!'",
"res": ["Error: unexpected EOF while parsing"]
}
总结
run
函数处理从客户端传递的 Python 代码,通过capture_print_output
捕获其输出并返回。capture_print_output
通过exec
动态执行 Python 代码,并通过重定向stdout
捕获print
输出。- 最终的输出通过
ok_res
返回给客户端,包含了代码及其执行结果。