「メモ」 カテゴリーの記事
Pythonでマルチスレッドプログラミングする(マルチスレッディング)
2010/7/22 木 0:41:06 by Lotus
今回はPythonにおけるマルチスレッドプログラミングについて。
そもそもマルチスレッドとはなにかといいますと、スレッドという処理の塊の単位を複数に分けること。たとえばCPUのコアが2つなら(デュアルコアCPU)、そのコア一つ一つに処理を割り振ったり。
まぁ並行処理させたり。
その辺はプリエンプティブマルチタスクとか、ノンプリエンプティブマルチタスクの話が絡んでくるのであれだけど。
OSが管理するのがプリエンプティブマルチタスク。アプリケーション自体がタスク、CPUを管理するのがノンプリエンプティブマルチタスク。
メリットとして、
処理の待ち時間の節約。
ネットワーク絡みの処理だとレスポンスまでに時間がかかってその間に処理をおこなう。
複数の処理を並列して行う。
など、メリットがある。リソースの有効な使い方ができる。
今回はそのマルチスレッドプログラミングをPythonで実装する。
Pythonのマルチスレッド機能は、OSのスレッド機能と密接に動くため、オーバヘッドが少ない。
Pythonにおけるマルチスレッドを行うにはthreadingモジュールのThreadクラスを継承すると簡単。他にもthreadingモジュールがある。(threadモジュールのthreadingとは別。)
threadingモジュールに定義されているThreadクラスがスーパークラスで、自分が作成するクラスはそれを継承したサブクラスになる。
このサブクラスではrun()というメソッド(関数)をオーバーライドする。
オーバーライドとはサブクラスでメソッドを再定義すること。書き換えるみたいな感じ。
__init__()メソッドも必要があるならオーバーライドする。初期化とか。
Threadの__init__()メソッドを継承しないとstart()とか使えない。
なお、run()メソッドは直接インスタンスから指定し実行うするのではなく、インスタンスからstart()メソッドを呼び出す。
そうすることで直接ではなく、間接的にrun()で定義した処理を行うことができる。直接run()を呼び出してはいけないみたい。
直接呼び出すと、プロンプトが戻らない(制御きかない。)
今回私はマルチスレッドを活かすため、ネットワークプログラミングにPythonのマルチスレッディングを使用した。
ネットワークプログラミングといっても簡単なもので、Socket通信による簡単なチャットシステム。
一つのスレッドでは処理をまっていないと(listen)いつ相手からメッセージがくるかわからない。
listenしながらも様々な処理を行うためにはどうしてもマルチスレッドを利用せざるを得ない…かも。
import socket from threading import Thread,Lock import thread import sys class SocketServer(Thread,object): def __init__(self): #super class init Thread.__init__(self) #socket settings self.s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) self.s.settimeout(1000) self.while_count = 0 self.while_flag=True self.data=[] #port number options if "-p" in sys.argv[1:]: self.port = sys.argv[sys.argv.index("-p")+1] try : self.port=int(self.port) except : print "Error! Port number is integer." sys.exit() #Default port number = 7777 else : self.port = 7777 #Main Thread. def run(self): print "=" * 50 print "Start the server program." print "Listening at : %s" % self.port print "=" * 50 print "Pending connections..." try: self.s.bind(('',self.port)) self.s.listen(10) except : print "Network error." print "Is the port number is already being used?" sys.exit() #While get recv while self.while_flag: self.conn,self.addr = self.s.accept() #print connect to if self.while_count == 0: print "Connected by %s " % self.addr[0] self.while_count=1 else : pass try : self.data=self.conn.recv(1024).encode("utf-8") self.conn.send("OK") if self.data == "exit": print "%s is closed the connection" % self.addr[0] self.data="=== Withdrawal ===" self.conn.close() except : print "Failed recv." self.conn.close() try : if len(self.data) !=0: print "-" * 50 print "%s => %s" % (self.addr[0],self.data) self.conn.close() except : pass self.conn.close() #Send to argument. def send(self,val): try : self.conn.send(val+"\n") except : print "Error! one more please." #Thread stop method def stop(self): self.while_flag=False try: print "wait..." self.conn.send("Please enter a space , charcter. exsample => [bye].") except: print "Please enter a space , charcter or a client" self.conn.close() print "Connection will be closed"
上記はSocket通信を使ったスレッドの例。
これだけではあまり意味をなさないが、上記の処理をバックグラウンド、というよりスレッドとして後ろで動くので、ネットワーク特有の処置待ちをしないですむ。
このプログラムは、Socket通信をする際、サーバとなるスレッド。
未完成だが、Clientがパケットを送信してくると、サーバのプロンプトにIPアドレスと送られてきた内容を表示する、など簡単なプログラムが組んである。
今、このマルチスレッディングの技術をつかって、開発中なので、また数日し、完成したらここにアップしようかと。
Python,set型
2010/6/1 火 18:19:45 by Lotus
メモ。
set型使えば、重複するデータとか、しないデータを管理するのに楽(?)
重複するデータが格納できない形。
Python2.4から組み込み関数になったが、2.4以前でもsetモジュールをインポートすれば使える。
2xは、
s=set([1,2,3,4,5])
みたいな記述が可能。
3xだと
s={1,2,3,4,5}
上記の書き方も可能。
{}を使うので辞書型と被りそう?(笑
sample.
s=set([1,2,3,4,5]) s2=set([4,5,6,7,8]) print s & s2 45
&を使うと、共通集合を使える。
unionメソッドとはunionというくらいなので、集合和。
intersectionメソッドは&と同じで、共通集合(重複している要素)を取り出すことが可能。
addとかremoveなどのメソッドが使える
メモでした