作为一个自动化测试人员,开发基本的应用桌面程序是必须的!最近在研究wxpython相关知识,目前看到多线程一块,发现官方文档介绍说:"在线程中不能修改修改窗口属性!",但是实际情况是:最近在做一个翻墙的简单APP。我开了2个线程一个线程用于显示设置进度(用的是第三方host,所以要下载host再覆盖本地host) ,一个线程处理下载任务,发现第一个线程中动态的设置self.gauge(value)可以生效,并没用到wx.CallAfter!! 需要注意的是,wxpython一次只能处理一个事件,避免同时在线程中启用用wx.CallAfter,这样wxpython还是一个一个去执行CallAfter传递函数。即:启用N个线程,N-1个用来干事情(不要在线程种使用CallAfter),第N个线程调用CallAfter通知主线程更新界面。上面说过了本人尝试了在线程中直接更改主窗口控件(不知道是否出现问题)。是可行的!但是,还是建议按照官方说法利用wx.CallAfter,以免发生异常崩溃。

wxpython多线程应用的常景:对于一些复杂任务的处理(比如下载若干文件),如果把这些代码全部放在主线程中,等你触发了这个事件后,应用程序会卡死,而且也触发不了其他时间,几乎处于一个假死状态(虽然他还活着...),这样的程序别说给别人用了,自己用都会崩溃....,所以就用到多线程,触发了下载事件后,在线程中完成任务,主线程干干嘛干嘛,但是要给一下提示给窗口程序,比如触发下载按钮时,主程序有"下载中..."等字样,下载完成后,线程通知窗口程序更新状态为"下载完成...",这样的交互至少是友善的。

wxpython多线程的使用方法:wxpython开发者建议的是使用wx.CallAfter+PubSub。CallAfter负者推送时间给主程序,PubSub实现wxPython应用程序与其他线程进行通信。

其实在wx.CallAfter中直接传一个主线程的方法,更简单!但是既然官方这样说,我们就这样用!!好吧我们来一个官方的例子,来看看wxpython如何使用的~

import time
import wx
from threading import Thread
from wx.lib.pubsub import Publisher ########################################################################
class TestThread(Thread):
"""Test Worker Thread Class.""" #----------------------------------------------------------------------
def __init__(self):
"""Init Worker Thread Class."""
Thread.__init__(self)
self.start() # start the thread #----------------------------------------------------------------------
def run(self):
"""Run Worker Thread."""
# This is the code executing in the new thread.
for i in range(6):
time.sleep(10)
wx.CallAfter(self.postTime, i)
time.sleep(5)
wx.CallAfter(Publisher().sendMessage, "update", "Thread finished!") #----------------------------------------------------------------------
def postTime(self, amt):
"""
Send time to GUI
"""
amtOfTime = (amt + 1) * 10
Publisher().sendMessage("update", amtOfTime) ########################################################################
class MyForm(wx.Frame): #----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial") # Add a panel so it looks the correct on all platforms
panel = wx.Panel(self, wx.ID_ANY)
self.displayLbl = wx.StaticText(panel, label="Amount of time since thread started goes here")
self.btn = btn = wx.Button(panel, label="Start Thread") btn.Bind(wx.EVT_BUTTON, self.onButton) sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.displayLbl, 0, wx.ALL|wx.CENTER, 5)
sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
panel.SetSizer(sizer) # create a pubsub receiver
Publisher().subscribe(self.updateDisplay, "update") #----------------------------------------------------------------------
def onButton(self, event):
"""
Runs the thread
"""
TestThread()
self.displayLbl.SetLabel("Thread started!")
btn = event.GetEventObject()
btn.Disable() #----------------------------------------------------------------------
def updateDisplay(self, msg):
"""
Receives data from thread and updates the display
"""
t = msg.data
if isinstance(t, int):
self.displayLbl.SetLabel("Time since thread started: %s seconds" % t)
else:
self.displayLbl.SetLabel("%s" % t)
self.btn.Enable() #----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MyForm().Show()
app.MainLoop()

上述代码我们随便搜索下wxpython多线程的应用多会举官方这个例子,可能是版本的问题(本人用的是wx-2.8),第一句就给来个错,网上search一下提出这个Publisher这个moudle不存在的问题是普遍的,但是没有相应的说法,现在就针对这个经典的wxpython程序剖析一下。这段代码本身是简单的,由于版本的问题可能出现如下问题。

1.ImportError: cannot import name Publisher

出现这个错误是正常的,我们进入wx.lib.pubsub这个模块发现并没有Publisher这个类,但是我们在wx.lib.pubsub这个模块下面的pub模块发现了Publisher的影子,原来在2.8版本时已经将这个类私有化了,见126行,_publisher = _Publisher(),同时将Publisher的subscribe与sendMessage复制给了subscribe与sendMessage变量见(128,131)行。所以我们这样引入头:from wx.lib.pubsub import pub,同时将所有的Publisher()改为pub。
2.TypeError: sendMessage() takes exactly 2 arguments (3 given)

经过1的修改,以为大功告成,运行依然报错崩溃。出现这个问题大多数人如果硬找问题原因很难找的,我们debug进出,发现他实例化的是"C:\Python27\Lib\site-packages\wx-2.8-msw-unicode\wx\lib\pubsub\core\kwargs\publisher.py"这个模块下的Publisher类,仔细一看sendMessage方法果然第二个参数应该传个字典类型的所有我们将本程序24,32,71行改为wx.CallAfter(pub.sendMessage, "update", msg="Thread finished!"),pub.sendMessage("update", msg=amtOfTime),t = msg。运行一下没问题~~注意sendMessage的键值(这里是msg)与subscribe监听方法种的接收参数(这里是msg)要相同,看源码其实就是msgKwargs这个字典参数来传递值的。

其实,这段代码没有问题的。我们注意到”C:\Python27\Lib\site-packages\wx-2.8-msw-unicode\wx\lib\pubsub\core\__init__.py" 的43行,其实core这个模块对于Publisher这个类的加载是动态的。我们进入policies.py这个模块第10行,发现msgDataProtocol = 'kwargs',原来如此...我们知道core模块下面有2个包一个是arg1,一个是kwargs,我们观察这2个包publisher模块下Publisher类的sendMessage方法是不一样的。原来我们这端代码用的是arg1下的这个Publisher类,好吧,我们将policies.py的第10行改为msgDataProtocol ='arg1',还原代码运行正确!!kwargs与arg1不同点是kwargs可以传递多个参数给主程序(**kwargs),而arg1只能是传递一个参数。

经过以上简单的论述,我们知道了wxpython是通过wx.CallAfter给主程序推入事件,通过PubSub与主程序传递数据。关于wxpython多线程的简单理解就是这样了,希望能提供帮助。

关于wxpython多线程研究包括(import Publisher错误研究)的更多相关文章

  1. 关于wxpython多线程研究包括(import Publisher等错误研究)

    作为一个自动化测试人员,开发基本的应用桌面程序是必须的!最近在研究wxpython相关知识,目前看到多线程一块,发现官方文档介绍说:"在线程中不能修改修改窗口属性!",但是实际情况 ...

  2. can not import Flask错误

    在学习flask官方文档——应用构建代码时,遇到了一个小问题照例子敲好代码以后出现了can not import  Flask错误,思考很久也没有解决,最后发现是因为应用模块和flask重名了.下面是 ...

  3. zz姚班天才少年鬲融凭非凸优化研究成果获得斯隆研究奖

    姚班天才少年鬲融凭非凸优化研究成果获得斯隆研究奖 近日,美国艾尔弗·斯隆基金会(The Alfred P. Sloan Foundation)公布了2019年斯隆研究奖(Sloan Research ...

  4. 一、美国国家经济研究局NBER教育经济研究项目工作论文合集

    一.美国国家经济研究局NBER教育经济研究项目工作论文合集 (一)项目地址: American National Bureau of Economic Research - Economics of ...

  5. (转)python requests 高级用法 -- 包括SSL 证书错误的解决方案

    我在使用requests访问某个https网站时出现错误  error::SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify fai ...

  6. python requests 高级用法 -- 包括SSL 证书错误的解决方案

    Session Objects会话对象 Session对象在请求时允许你坚持一定的参数.此外,还坚持由Session实例的所有请求的cookie. 让我们坚持在请求时使用 s = requests.S ...

  7. 在nodeJs的Express框架下用TypeScript编写router路由出现import关键字错误的解决方案

    问题出现场景 在项目中采用nodejs做中间层,做页面的首屏渲染,同时采用express作为主web框架,其中express的router页面路由我采用ts语言来编写.如下: //page.ts 文件 ...

  8. java多线程开发容易犯的错误

    昨天在社区上看到有人讨论多线程使用,多线程遇到一些问题以及一些使用技巧记录一下.为什么要使用多线程, 不能是为了用而用,和设计模式一样用的合理,会让程序更易于理解,用的不合理反而会让程序变得更难理解. ...

  9. import torch错误解决

    import torch出现 ”from torch._C import * ImportError: DLL load failed: 找不到指定的模块“错误这里torch=1.0.1,torchv ...

随机推荐

  1. C# winform ListView+CheckBox的做法

    1.设置ListView的属性:CheckBoxs=true 2.ListView字段第一列文本框为空,把工具箱里面的CheckBox控件拖到ListView的第一个字段做全选/全不选的控件. 3.C ...

  2. Eclipse格式化代码换行、删除空行

    Java代码 Window-preference-Java-Code Style-Formatter|Edit...-Line Wrapping|Maximum line width: 修改一行最大长 ...

  3. HMX-Server C++ 分步式服务器大版本更新了(有源码)

    原文地址:http://www.cnblogs.com/hellohuang/p/6294763.html # HMX-ServerHMX-Server分步式服务器框架,主要分为网关.登录.世界.场景 ...

  4. java算法 蓝桥杯 乘法运算

    问题描述 编制一个乘法运算的程序. 从键盘读入2个100以内的正整数,进行乘法运算并以竖式输出. 输入格式 输入只有一行,是两个用空格隔开的数字,均在1~99之间(含1和99). 输出格式 输出为4行 ...

  5. vue-router跳转页面

    小结放在前:先祝大家新年快乐!鸡年大吉大利!在新的一年里大家都有跳跃般的成长!作为新年的第一篇文章,就拿他来给大家拜个年!!!文章前部份讲解了vue-router路由的配置,后半部分为去年的文章vue ...

  6. js中的正则表达式入门

    什么是正则表达式呢? 正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个字符串是否含有某种子串.将匹配的子串做替换或者从某个字符串中取出符合某个条件的子串等 ...

  7. 论SNAPSHOT包的危害性

    先介绍一下背景:我们应用是一个标准的spring+webx工程,博主在一次项目发布前为了再次测试一下自己的代码,将分支部署到日常环境中,但是项目启动的时候报错: 第一眼看到这个堆栈后有点懵逼 第一是上 ...

  8. this的相关介绍与用法

    当一个对象创建后,Java虚拟机(JVM)就会给这个对象分配一个引用自身的指针,这个指针的名字就是this.因此,this只能在类中的非静态方法中使用,静态方法和静态的代码块中绝对不能出现this,并 ...

  9. 关于hibernate注解的简单应用

    @Override 用途:重写父类的同名方法 单元测试注解 @Test 用途:用于测试 @Before 用途:单测方法走之前执行 @After 用途:单测方法走之后执行 注解的目标:替换小配置.替换h ...

  10. 获取url地址参数值

    获取url地址参数值方法: function GetQueryString(name) { var reg = new RegExp("(^|&)" + name + &q ...