turtle-graphics - Streamlit 在多次运行海龟绘图时崩溃
问题描述
介绍
我正在构建一个绘图应用程序,使用Streamlit库作为前端,Turtle库作为绘图引擎。
问题
当多次调用绘图时,Streamlit 崩溃并抛出以下消息:
Exception ignored in: <function Image.__del__ at 0x0000017A47EF3558>
Traceback (most recent call last):
File "c:\users\johnsmith\anaconda3\lib\tkinter\__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Tcl_AsyncDelete: async handler deleted by the wrong thread
我希望用户能够更改输入并根据需要多次重新运行应用程序而不会崩溃。
代码
前端:
# frontend.py
import streamlit as st
from backend import *
st.title("Turtle App")
title = st.text_input("Canvas Title", value="My Canvas")
width = st.number_input("Canvas Width", value=500)
height = st.number_input("Canvas Height", value=500)
length = st.number_input("Square Length", value=200)
clicked = st.button("Paint")
if clicked:
canvas_builder(title, width, height, length)
后端:
# backend.py
import turtle
def canvas_builder(title, canvas_width, canvas_height, square_length):
CANVAS_COLOR = "red"
PEN_COLOR = "black"
scr = turtle.Screen()
scr.screensize(canvas_width, canvas_height)
scr.title(title)
scr.bgcolor(CANVAS_COLOR)
turtle.setworldcoordinates(0, 0, canvas_width, canvas_height)
t = turtle.Turtle()
t.color(PEN_COLOR)
t.begin_fill()
for i in range(4):
t.forward(square_length)
t.left(90)
t.end_fill()
turtle.done()
再生产
- 同一文件夹中的所有文件
- 在同一文件夹中的 Conda 提示符下,运行:
streamlit run ./st.py
- 按照shell指示在浏览器中打开应用程序
- 按 UI 底部的“绘画”按钮
- 关闭海龟窗口
- 再次按下“绘画”按钮
- 检查streamlit app的错误提示
笔记
- 这似乎是tkinter进程的问题。我试图抓住根/主根并杀死它,但它没有用。
- 理想情况下,我想将 Turtle 窗口作为绘图嵌入到 streamlit 应用程序中。
- 我不想替换 streamlit 和/或海龟。
解决方案
我通过在子进程中运行 turtle 解决了这个问题。新的frontend.py代码:
import multiprocessing
import streamlit as st
from backend import *
st.title("Turtle App")
title = st.text_input("Canvas Title", value="My Canvas")
width = st.number_input("Canvas Width", value=500)
height = st.number_input("Canvas Height", value=500)
length = st.number_input("Square Length", value=200)
clicked = st.button("Paint")
t = multiprocessing.Process(target=canvas_builder, args=(title, width, height, length,))
if clicked:
t.start()
推荐阅读
- react-native-popup-menu - 如何在弹出菜单中添加偏移量?
- elasticsearch - Elasticsearch 中的无痛脚本通过条件检查来操纵分数
- javascript - 将 HTML 解析为组成标签
- c# - 发布目标中缺少 VS 2019 天蓝色功能
- ruby - 未初始化的常量 Van (NameError)
- vuejs2 - 在Vue中设置包装对象的子组件的道具
- powerbi - MS Graph beta/applications OData 属性“resourceSpecificApplicationPermissions”在类型“microsoft.graph.apiApplication”上不存在
- mongodb - 无法在 MongoDB 中使用聚合运算符(storageEngine=mmapv1)
- javascript - jQuery filter() 用于已加载数据的国家/州/城市列表(无 ajax 调用)
- html - 如何将绝对元素居中在另一个绝对元素中,可用于旋转和动画目的