转到Ubuntu学习已经很长时间,另外在VirtualBox虚拟机中安装了WinXP,以检测跨平台的问题。
关于多线程,我想实现的功能具体是:子线程运算,更新主线程进度条; 子线程调用外部进程获取返回值,更新主线程进度条
文本编码问题
在我的第一个wxpython程序的第一个版本中,我为了在windows系统下正确显示中文,大量采用了
.encode('gbk')
的输出方式,然而这种方式在默认编码为UTF-8的Linux系统下无法正常显示。
so how to solve it?
下面是我的解决方法:
1, 在win下安装wxpython的unicode版本,直接传unicode字符串给wxpython相关方法,即可显示中文
2, 调用外部命令等必须严格按照系统编码的时候,可以采用下面的编码方式(当然,先import sys):
.encode(sys.getfilesystemencoding())
这样即可达到相当好的跨平台兼容性:)
多线程问题
先来看第一个程序:子线程运算,更新主线程进度条
(程序目的是计算MD5)
import threading, hashlib, os
class TRun(threading.Thread):
def __init__(self, caller):
threading.Thread.__init__(self)
self.caller = caller
def run(self):
global file
m1 = hashlib.md5()
f = open(file,'rb')
f1 = os.stat(file)
size = f1.st_size
now = 9728000
bytes = f.read(9728000)
while(bytes != ''):
m1.update(bytes)
i=now*100/size
if(i>100): i=100
wx.CallAfter(self.caller.updateProgress1, i)
bytes = f.read(9728000)
now+=9728000
f.close()
#然后在窗体Frame类里加入如下方法:
def updateProgress1(self, i):
self.flag = self.progress.Update(i)
#调用TRun类的方法
self.progress = wx.ProgressDialog(u"标题...", u"内容, 请稍候…", 100, style=wx.PD_AUTO_HIDE)
self.t = TRun(self)
self.t.setDaemon(True)
self.t.start()
#self.t.join() #如果需要等待子线程运行完再继续,去掉此行的注释
稍作解释:
1, wx.ProgressDialog进度条的wx.PD_AUTO_HIDE属性,作用是进度条满格后自动隐藏
2, wx.CallAfter方法的作用是让主线程执行函数(子线程是无权修改主线程界面元素的,包括进度条)
下面则是调用外部程序(以par2为例),获取返回值并修改主程序进度条的功能实现:
class TRun2(threading.Thread):
def __init__(self, caller):
threading.Thread.__init__(self)
self.caller = caller
def run(self):
global file
ans=''
arg='par2 c -r3 \"'+file.encode(sys.getfilesystemencoding())+'.par2\" \"'+file.encode(sys.getfilesystemencoding())+'\"'
import subprocess
p = subprocess.Popen(args=arg,stdout=subprocess.PIPE, shell=True)
r1 = re.compile('Constructing[:\s]*([\d\.]+)%')
r2 = re.compile('Processing[:\s]*([\d\.]+)%')
r1yes = False
while p.poll()==None:
ans+=p.stdout.read(100)
if not r1yes:
k = r1.findall(ans)
k2 = r2.findall(ans)
if len(k2)>0:
r1yes = True
time.sleep(0.3)
else:
k = r2.findall(ans)
if len(k)>0:
wx.CallAfter(self.caller.updateProgress1, int(float(k[-1])))
time.sleep(0.01)
#其他部分/调用方法与上例相同
下面仍然做一些解释:
1, 使用time.sleep(n)函数作用为延迟n秒(类似QBASIC的SLEEP)
2, 调用外部进程使用了subprocess.Popen()函数,以PIPE的方式获取stdout返回值,shell参数的意义是使用shell语法解析外部命令。
如果不需要使用shell,则arg需要修改为
arg=['par2','c','-r3',file.encode(sys.getfilesystemencoding())+'.par2',file.encode(sys.getfilesystemencoding())]
#将参数作为列表元素传入
3, 获取进度采用了正则表达式匹配,因为par2过程主要是constructing和processing耗时,因此让进度条走两次。此处我给的方法只是”可行“而已,不一定很好
参考资料:补充中
为啥用 wxPython,用 pygtk 不好么,我看到用 pygtk 的比较多点=,=
我用 wxPython 的原因是想用它的 native 控件…
相识在于缘,相知在于诚,有老朋友的时候,能结识一些您这样新好朋友感到荣幸。
来学习一下博主的文章!写的不错!支持了!
OMG sleipnir 终于升级到 IE 8.0 了。。
test 在你这测试下。。猫猫同学
我是过来支持你的,呵呵。。.
路口看看 支持一下
过来,看看有没更新!!
拜访这里,呵呵,留名纪念
打酱油路过,嘿嘿~~!
呵呵,学习一下
我是来沙发的,因为我只用python做了个hello world。。。
+1
我是来沙发的,因为我只用python做了个hello world。。。