小试Python多线程

来源:互联网 发布:知乎比天涯好吗 编辑:程序博客网 时间:2024/06/06 01:02

Python多线程相比其它语言实现起来要简单一点。最近做的工作是使用多线程将多个文件上传至新浪微盘。下面简要总结一下Python的多线程知识。

一、Python多线程知识

1. threading模块。
threading模块提供了各种非常好的同步机制,使用起来比较方便。threading的Thread类是我们比较常用的线程模块,可以从这个Thread类中派生出一个子类,创建这个子类的实例,然后调用它的start()方法,来开始线程的执行。在这个子类中,我们需要重写run方法,让这个子类完成我们需要的功能。

2. Queue模块
Queue模块可以用来进行线程间通讯,让各个线程之间共享数据。
1). 可使用put(item, block=0)方法向队列中放置item,如果block=False,则将item放置到队列中并且不阻塞,如果队列是满的,则立即抛出异常。如果block参数不为0,且带有timeout参数,并且timeout是正数,则put阻塞timeout所指定的时间,如果队列还是满的,则抛出Full异常。
2). 可使用get()方法来从队列中取出数据,它也有block参数和timeout参数,这两个参数和put方法中的参数类似,如果队列空的情况下get参数,则可能会抛出Empty Exception。从Python手册的信息上来看,get和put方法是线程安全的。
3).Queue的empty和full方法可以用来判断队列是否为空和满。如果队列为空则empty返回True,如果队列满则Full返回True。

二、Python多线程使用举例

下面给出我写的关于使用Python多线程向新浪微盘上传文件的代码
1).线程管理类,它向队列分配任务,并启动多线程。这里,我往queue队列中放置了一个列表,存放在线程中需要使用的数据。并建立了一个thread列表,存放指定数目的线程,然后将线程启动执行。Queue的join方法会阻塞等待所有线程执行完毕。
class UploadThreadHandler():def __init__(self, list_widget, cloud_path, access_token, thread_num=5):self.access_token = access_tokenself.threads = []count = list_widget.count()self.m_queue = Queue.Queue(count)if count == 0:returnfor i in range(count):  # 初始化队列self.m_queue.put((list_widget.item(i), cloud_path, list_widget))for i in range(thread_num):  # 初始化线程池self.threads.append(UploadThread(self.m_queue, self.access_token))self.threads[i].setName("i")self.threads[i].start()def wait_complete(self):self.m_queue.join()
2).线程类,线程类的代码如下所示,在run方法中,while循环不断从queue中取出列表信息,然后根据列表信息,来执行文件的上传工作。若队列已空,则get抛出异常,从而导致线程结束。其余代码,可忽略。
class UploadThread(threading.Thread):def __init__(self, queue, access_token):"""path 是本地的路径"""threading.Thread.__init__(self)self.m_queue = queueself.access_token = access_tokenself.client = client(self.access_token)self.exitFlag = Falsedef run(self):"""上传文件"""print "start upload thread"while self.exitFlag is not True:if self.m_queue.empty():breaktry:item, cloud_path, list_widget = self.m_queue.get()if (item.text() == QtCore.QString("成功上传...".decode("utf-8"))):continuesha1 = Util.q_string2str(item.text())sha1 = sha1[sha1.rindex("\\") + 1:]result, is_success = self.client.files_put(cloud_path + sha1, item.text())print result, is_successif is_success:params = {"name": sha1, "option": "fragmentation"}url = ConfigUtil.read_ops("config.config", "server_address", "address") + \ConfigUtil.read_ops("config.config", "sub_address", "upload_state")netutil.sendPost(url, params)result = JsonUtil.str2json(result)if "error" in result.keys():continueprint "成功上传文件" + cloud_path + sha1item.setText("成功上传...".decode("utf-8"))except Exception, e:print Exception, ebreakfinally:self.m_queue.task_done()print "upload thread end"

以上代码测试了几次暂时没有发现什么错误,可以利用多线程多连接向新浪微盘同时上传多个文件,比较快的。若连接开多了则新浪微盘会拒绝连接的。

0 0