小試Python多線程

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_token
		self.threads = []
		count = list_widget.count()
		self.m_queue = Queue.Queue(count)
		if count == 0:
			return
		for 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 = queue
		self.access_token = access_token
		self.client = client(self.access_token)
		self.exitFlag = False

	def run(self):
		"""上傳文件"""
		print "start upload thread"
		while self.exitFlag is not True:
			if self.m_queue.empty():
				break
			try:
				item, cloud_path, list_widget = self.m_queue.get()
				if (item.text() == QtCore.QString("成功上傳...".decode("utf-8"))):
					continue
				sha1 = 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_success
				if 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():
						continue
					print "成功上傳文件" + cloud_path + sha1
					item.setText("成功上傳...".decode("utf-8"))
			except Exception, e:
				print Exception, e
				break
			finally:
				self.m_queue.task_done()
		print "upload thread end"

以上代碼測試了幾次暫時沒有發現什麼錯誤,可以利用多線程多連接向新浪微盤同時上傳多個文件,比較快的。若連接開多了則新浪微盤會拒絕連接的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章