社区导航

 
查看: 589|回复: 0

[分享] 解决python2.x + wxpython多线程时导入wx.lib.pubsub提示语法错误问题的方法

[复制链接]

1272

TA的帖子

4

TA的资源

纯净的硅(高级)

Rank: 6Rank: 6

发表于 2018-7-12 15:00:11 | 显示全部楼层 |阅读模式
本帖最后由 wsmysyn 于 2018-7-12 17:58 编辑

RT

背景:
最近准备用python + wxpython多线程的方式进行自动测试;环境是windows10  + python2.7.15 + wxpython4.0.3
由于自动测试需要与下位机长时间通信会占用很长时间,如果不用多线程会一直阻塞UI界面造成假死。

问题现象:
网上找了一篇多线程的教程。。满心欢喜尝试了一下,发现,提示 如下语法错误:


感觉很奇怪,为什么自动安装的包会提示语法错误呢(python3的语法我并不没有看过。
在包安装目录里的说明发现了如下提示:

提示4.0.0版本已经放弃支持python2.x了,那问题来了,为什么python2,他还会下载不支持python2的包呢??

解决方法:
既然不支持那就找支持的包;pip默认安装的pypubsub都是最新的包
通过pip install PyPubSub==3.3.0可以强制安装低版本的包
(3.3.0版本是开始随便输一个版本号,pip会提示出当前正确的版本号有哪些,选择一个最低的就是3.3.0了)
在包目录查看note确认可以支持python2.
安装好以后再运行脚本,发现已经不提示语法错误了。问题解决。。。




参考
以下为网上关于wxpython多线程的方法
前段时间我编写了一个工业控制的软件,在使用中一直存在一个问题,就是当软件检索设备时,因为这个功能执行的时间比较长,导致GUI界面假死,让用户分辨不清楚软件到底仍在执行,还是真的挂掉了。(虽然我设计了同步log显示,但是这个也同样假死了)

程序截图如下:

代码解析如下:
  1. # -*- coding: utf-8 -*-

  2. import time
  3. import wx
  4. from threading import Thread
  5. from wx.lib.pubsub import Publisher
复制代码



time库用来执行定时函数,模拟需要长时间执行的功能。Publisher用来在线程间传输消息。
  1. class TestThread(Thread):
  2. def __init__(self):
  3.   #线程实例化时立即启动
  4.     Thread.__init__(self)
  5.     self.start()
  6.     def run(self):
  7.   #线程执行的代码
  8.     for i in range(101):
  9.         time.sleep(0.03)
  10.         wx.CallAfter(Publisher().sendMessage, "update", i)
  11.        time.sleep(0.5)
  12.     wx.CallAfter(Publisher().sendMessage, "update", u"线程结束")
复制代码



TestThread的__init__函数,定义线程实例化时就启动,run函数就是需要长时间执行的程序。
wx.CallAfter与Publisher().sendMessage用来向GUI发送消息。
  1. class MyForm ( wx.Frame ):
  2. def __init__( self, parent ):
  3.     wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"Leniy,20140627", pos = wx.DefaultPosition, size =       wx.Size( -1,-1 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
  4.     self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
  5.     gSizer2 = wx.GridSizer( 0, 3, 0, 0 )
  6.     self.m_button2 = wx.Button( self, wx.ID_ANY, u"执行线程", wx.DefaultPosition, wx.DefaultSize, 0 )
  7.     gSizer2.Add( self.m_button2, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 5 )
  8.     self.m_staticText2 = wx.StaticText( self, wx.ID_ANY, u"MyLabel", wx.DefaultPosition, wx.DefaultSize, 0 )
  9.     self.m_staticText2.Wrap( -1 )
  10.     gSizer2.Add( self.m_staticText2, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 5 )
  11.     self.m_gauge1 = wx.Gauge( self, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, wx.GA_HORIZONTAL )
  12.     self.m_gauge1.SetValue( 0 )
  13.     gSizer2.Add( self.m_gauge1, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 5 )
  14.     self.SetSizer( gSizer2 )
  15.     self.Layout()
  16.     gSizer2.Fit( self )
  17.     self.Centre( wx.BOTH )
  18.     self.m_button2.Bind( wx.EVT_BUTTON, self.onButton )
  19.     Publisher().subscribe(self.updateDisplay, "update")
  20. def updateDisplay(self, msg):
  21.     t = msg.data
  22.     if isinstance(t, int):#如果是数字,说明线程正在执行,显示数字
  23.         self.m_staticText2.SetLabel("%s%%" % t)
  24.         self.m_gauge1.SetValue( t )
  25.     else:#否则线程未执行,将按钮重新开启
  26.         self.m_staticText2.SetLabel("%s" % t)
  27.         self.m_button2.Enable()
  28. def onButton( self, event ):
  29.     TestThread()
  30.     self.m_staticText2.SetLabel(u"线程开始")
  31.     event.GetEventObject().Disable()
复制代码



这个就是GUI的主程序,__init__中使用Publisher().subscribe(self.updateDisplay, “update”)声明了获取线程消息以及显示的方法。
  1. if __name__ == "__main__":
  2.     app = wx.PySimpleApp()
  3.     MyForm(None).Show()
  4.     app.MainLoop()
复制代码


最后将窗口MyForm(None).Show()显示出来,程序就完成了。



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
坐而言不如起而行


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

Archiver|手机版|小黑屋|电子工程世界 ( 京ICP证 060456 )

GMT+8, 2018-12-14 06:56 , Processed in 0.066536 second(s), 16 queries , Gzip On, MemCache On.

快速回复 返回顶部 返回列表