关于wxpython多线程研究包括(import Publisher等错误研究)
作为一个自动化测试人员,开发基本的应用桌面程序是必须的!最近在研究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等错误研究)的更多相关文章
- 关于wxpython多线程研究包括(import Publisher错误研究)
作为一个自动化测试人员,开发基本的应用桌面程序是必须的!最近在研究wxpython相关知识,目前看到多线程一块,发现官方文档介绍说:"在线程中不能修改修改窗口属性!",但是实际情况 ...
- Android开发-解决 AIDL 中找不到couldn't find import for class错误
最近在使用AIDL做IPC的时候,在处理复杂的数据类型的时候,编译器总是报couldn't find import for class错误,所以在这里总结下AIDL使用的时候的一些注意事项,希望对你能 ...
- 解决nextjs部署到now上之后出现的“Unable to import module 'now__launcher'”错误
解决nextjs部署到now上之后出现的“Unable to import module 'now__launcher'”错误 这个错误是由于在next.config.js中直接引用了withLess ...
- c#中多线程同步Lock(锁)的研究以及跨线程UI的操作
本文只针对C#中,多线程同步所用到的锁(lock)作为研究对象.由于想更直观的显示结果,所以,在做demo的时候,就把多线程通过事件操作UI的代码也写了出来,留作备忘和分享吧. 其实多线程的同步,使用 ...
- wxpython多线程通信的应用-实现边录音边绘制音谱图
#!bin/bash/python # -*- coding=utf-8 -*- from __future__ import division import threading import wx ...
- wxpython多线程间通信
#!bin/bash/python # -*- coding=utf-8 -*- import time import wx from threading import Thread from wx. ...
- c#中多线程同步Lock(锁)的研究以及跨线程UI的操作 (转)
https://www.cnblogs.com/tommyheng/p/4104552.html 本文只针对C#中,多线程同步所用到的锁(lock)作为研究对象.由于想更直观的显示结果,所以,在做de ...
- C# 多线程 Parallel.ForEach 和 ForEach 效率问题研究及理解
from:https://blog.csdn.net/li315171406/article/details/78450534 最近要做一个大数据dataTable循环操作,开始发现 运用foreac ...
- python ssh弱口令爆破多线程脚本及遇到的一些错误与问题
练习写了个SSH弱口令爆破多线程脚本,遇到的问题 1.一开始想import pexpect 中的pxssh 然而却一直该有错误, ImportError: cannot import name spa ...
随机推荐
- leetcode — triangle
/** * Source : https://oj.leetcode.com/problems/triangle/ * * * Given a triangle, find the minimum p ...
- JVM(一)史上最佳入门指南
提到Java虚拟机(JVM),可能大部分人的第一印象是"难",但当让我们真正走入"JVM世界"的时候,会发现其实问题并不像我们想象中的那么复杂.唯一真正令我们恐 ...
- Perl List::Util模块用法详解
本文介绍Perl标准库List::Utils中的列表工具,有时候它们非常好用.比如Perl中测试列表中是否包含某个元素(某个元素是否存在于列表中)没有比较直接比较方便的功能,但使用List::Util ...
- C# 常用小点
1]创建文件夹 //相对路径 string FilePath = Server.MapPath("./") + "ImageFile/Images/" + Da ...
- Unity的四元素与Vector3的乘积的含义
Quaternion.Euler(x,y,z)含义是按照每个旋转轴以x,y,z旋转度旋转,例子:Quaternion.Euler(45,45,45) Quaternion与Vector3的右乘操作(* ...
- Scrapy-Redis分布式爬虫常规操作
一.X-path 的常规用法1./是从根节点选取,有顺序2.//从当前节点选择文档中的节点,无顺序3..选取当前节点4...选取当前节点的父节点5.@选取属性6. //div[@class='docl ...
- Java开发笔记(二十)一维数组的用法
之前介绍的各类变量都是单独声明的,倘若要求定义相同类型的一组变量,则需定义许多同类型的变量,显然耗时耗力且不宜维护.为此,编程语言引入了数组的概念,每个数组都由一组相同类型的数据构成,对外有统一的数组 ...
- Java消息中间件----ActiveMQ入门①
一 首先到ActiveMQ下载安装包 Active官网地址http://activemq.apache.org/activemq-5150-release.html 如图所示,有两个下载的链接,我们下 ...
- Spring笔记01_下载_概述_监听器
目录 Spring笔记01 1.Spring介绍 1.1 Spring概述 1.2 Spring好处 1.3 Spring结构体系 1.4 在项目中的架构 1.5 程序的耦合和解耦 2. Spring ...
- Vue-指令
1. v-text:这个指令用于将vue实例中的data内的属性渲染到标签内.有两种写法: 1. `<div v-text="数据"></div>`:该写法 ...