Python exec执行Streamlit用户代码的全局局部变量作用域问题求解
解决方案
直接给exec传入统一的自定义命名空间字典即可,无需硬编码预设用户变量,也不需要要求用户加global声明,同时还能避免用户代码污染主程序的命名空间。
实现代码
import streamlit as st # 1. 初始化用户专属命名空间,可提前注入你要暴露给用户的API、预设变量 user_ns = { "h1": st.header, "a": 0, "b": 0, # 其他要开放给用户的组件、工具函数都可以提前存入该字典 } # 2. 获取用户输入的代码 code = code_editor() # 3. 执行用户代码,将全局、局部命名空间都指定为同一个自定义字典 exec(code, user_ns, user_ns) # 4. 你如果需要取用用户代码生成的变量,直接从命名空间字典读取即可 if "output" in user_ns: st.write("用户代码生成的output值:", user_ns["output"])
实现原理
Python的exec函数支持传入globals和locals两个参数指定执行代码时的全局、局部命名空间:
- 默认场景下
exec使用主程序当前的全局、局部命名空间,用户代码的函数内部修改变量会被识别为局部变量,因此会抛出未定义错误 - 当你将
globals和locals都指定为同一个字典时,用户代码的所有变量操作都会落到该字典内,行为和用户本地写Python脚本完全一致,函数内修改外层变量不需要额外加global声明,任意长度的用户代码产生的所有变量都会自动存入该字典,无需硬编码处理。
额外安全提示
公开站点直接后端执行用户提交的exec代码存在极高安全风险,用户可执行任意系统指令。如果你的站点面向公网开放,建议切换为Pyodide方案在用户浏览器端执行Python代码,完全隔离后端环境,适配Streamlit的前端交互场景。
内容的提问来源于stack exchange,提问作者Lucid
相关产品推荐
相关产品推荐

