【问题标题】:Why is my python code not working ONLY when I multithread - Tkinter为什么我的 python 代码仅在我多线程时不起作用 - Tkinter
【发布时间】:2015-10-09 16:14:53
【问题描述】:

我的代码中有一些奇怪的地方,我在网上的任何地方都找不到解决方案(至少我试过了)。

代码在 1 个线程上完美运行。

for i in range(1):

当我尝试增加线程数时,

for i in range(3):

代码停止正确运行(验证码 GUI 停止显示,没有错误,只是停止显示)

我正在尝试做的是使用 tkinter GUI 弹出验证码供用户解决。

这是我的代码的一个非常简化的版本,仅用于这篇文章。

import requests,cStringIO, PIL , Queue
from Functions import *
from PIL import ImageTk
import Tkinter as tk
from Tkinter import *
import threading

__author__ = 'user'
Session = {'view_state': '', 'event_validation': ''}
threadLock = threading.Lock()

class PopCaptcha( Frame  ):
    def __init__( self , img):

        def onok(event=None):
            self.captchaText = self.entry1.get()
            self.captchaThread = 1
            self.master.destroy()

        self.captchaThread = 0
        self.captchaText = ""
        tk.Frame.__init__(self)

        self.pack()
        self.master.title("Enter Captcha")

        image1 = PIL.Image.open(img)
        tkpi = ImageTk.PhotoImage(image1)

        self.picture1 = Label(self, image=tkpi)
        self.picture1.image = tkpi
        self.picture1.grid(row= 1)

        self.entry1 = Entry(self , font=('Helvetica', '14'))
        self.entry1.grid(row= 2)

        self.button1 = Button( self, text = "SUBMIT", width = 25,
                               command = onok )
        self.button1.grid( row = 3)

        self.master.bind('<Return>', onok)
        self.master.protocol("WM_DELETE_WINDOW", self.on_closing)


    def on_closing(self):
        self.captchaThread = 1
        self.master.destroy()




class TestClass:
    def __init__(self):
        self.error = ""
        self.status = ""
        self.captchaTries = 0

    def DoThing(self):
        self.status = ""
        self.error = ""
        self.captchaThread = 0

        captchaurl = "https://upload.wikimedia.org/wikipedia/commons/6/69/Captcha.jpg"


        hr = requests.get(captchaurl)
        captchafile = cStringIO.StringIO(hr.content)

        while self.status is not "OK" or self.error == "WrongCaptcha":
            self.captchaTries += 1

            if (self.captchaTries > 3):
                hr = requests.get(captchaurl)
                captchafile = cStringIO.StringIO(hr.content)
                self.captchaTries = 0



            print "Preparing Captcha..."
            threadLock.acquire()
            captcha = PopCaptcha(captchafile)
            print "Showing Captcha..."
            captcha.mainloop()
            print "Captcha Showen"
            threadLock.release()


            while captcha.captchaThread == 0:
                pass


            Session['Captcha'] = captcha.captchaText

            PostData = {
                'Captcha' : Session['Captcha']
            }

            headers = {
                'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0',
                'X-Requested-With': 'XMLHttpRequest',
                'X-MicrosoftAjax' : 'Delta=true',
                'Pragma' : 'no-cache',
                'content-type': 'application/x-www-form-urlencoded; charset=utf-8',
                'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                'Accept-Charset' : 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
                'Accept-Language' : 'en-US,en;q=0.5'
            }

            print "Attempting to post ..."
            r = requests.post("http://google.com", data=PostData, headers=headers)

            if 1:
                print "FAILED"
                self.error = "WrongCaptcha"
            else:
                print "WORKED"
                self.error = "NoError"
                self.status = "OK"


print "Welcome to MD5 Cracker!"
threads = []


for i in range(3):
    hk = TestClass()
    t = threading.Thread(target=hk.DoThing)
    threads.append(t)

for x in threads:
    x.start()
    print "Thread started"

我的代码有什么我不知道的问题吗? 如何解决这个问题?

谢谢

【问题讨论】:

    标签: python multithreading tkinter captcha


    【解决方案1】:

    Tkinter 不是线程安全的。您正在尝试在多个线程中创建小部件,这很少奏效。

    也许可以在每个线程中创建单独的根窗口,但我从未尝试过这样的事情。您可以在没有线程的情况下执行此操作,但很难理解为什么要为每个线程创建小部件。

    通常在多线程 tkinter 应用程序中,您有一个包含小部件的线程,然后其他线程执行数据处理并将更改放入 GUI 线程读取的队列以更新其显示。

    【讨论】:

    • 你有 Tkinter 不是线程安全的声明的来源吗?
    • @steffen:我没有 100% 确定的来源(即:tkinter 或 tk 文档中没有声明说“tkinter 不是线程安全的”)。然而,Donal Fellows 是 tcl/tk 项目(构建 tkinter)的核心维护者之一,他对这里的情况做了很好的解释:stackoverflow.com/a/38767665/7432。如果多纳尔不是最权威的信息来源,那么他在前两或前三名。
    猜你喜欢
    • 2011-05-31
    • 1970-01-01
    • 2017-09-19
    • 1970-01-01
    • 2014-01-23
    • 2013-08-06
    • 1970-01-01
    • 2013-05-08
    相关资源
    最近更新 更多