Python3でmultiprocessingを使ってみる。
pythonの並列プログラミングを修得するために、今回はmultiprocessingを使いたい思います。コードは至って簡単。関数1で乱数生成し他のプロセスにデータ送り、そのデータを他のプロセスで生成された関数2が表示します。
17.2. multiprocessing — プロセスベースの並列処理 — Python 3.4.3 ドキュメント
#!/usr/bin/env python3 ## producer_taskがランダムな数字を送り、consumer_taskがそれを受け取り表示する。 import os ,random from multiprocessing import Process, Pipe ## Pipe :: 2つのプロセスで情報のやりとりをする。 ## Process :: プロセスを生成する。データの非同期的に実行するならば、このオブジェクトだけを使えばいい。 def producer_task(conn): value = random.randint(1,10) conn.send(value) print('Value [%s] sent by PID [%d]' % (value, os.getpid())) ## os.getid()を出力することで、マルチプロセッシングが出来ていることを確認する。 conn.close() def consumer_task(conn): print('Value [%d] received by PID [%d]' % (conn.recv(), os.getpid())) if __name__ == '__main__': producer_conn, consumer_conn = Pipe() consumer = Process(target=consumer_task,args=(consumer_conn,)) producer = Process(target=producer_task,args=(producer_conn,)) consumer.start() producer.start() consumer.join() producer.join()
出力
Value [9] sent by PID [14808] Value [9] received by PID [14807]
参考文献
Parallel Programming With Python
- 作者: Jan Palach
- 出版社/メーカー: Packt Publishing
- 発売日: 2014/06/25
- メディア: ペーパーバック
- この商品を含むブログを見る
Pythonのプログラムをメモリ管理する。
Pythonってメモリ使いすぎる...。てことで、標準モジュールのresourceを使って、使用メモリのサイズを制限しましょう。
#!/usr/bin/env python # coding:utf-8 import resource rsrc = resource.RLIMIT_AS soft, hard = resource.getrlimit(rsrc) ## Memory sizeの制限 ## 現在の設定を取得 ## softはユーザーで設定、hardはスーパーユーザーで設定できる。 soft = 1024 resource.setrlimit(rsrc,(soft,hard)) ## 1024バイト、-1はシステムで許されている上限を設定。 rsrc = resource.RLIMIT_CPU ## CPU使用時間の制限:単位(秒) resource.setrlimit(rsrc,(0.01,hard)) ## このプロセスのリソースの使用状態を把握する print getattr(resource.getrusage(resource.RUSAGE_SELF),'ru_utime') ## ユーザモードの実行時間 print getattr(resource.getrusage(resource.RUSAGE_SELF),'ru_ixrss') ## 共有メモリのサイズ
numpyのarrayからwhereを使って、指定した2つ以上の条件の要素を取り出す方法。
まずは、nnumpyp.whereの紹介。
mat =\ [[ 0 1 2 3 4 5 6 7 8 9] [10 11 12 13 14 15 16 17 18 19] [20 21 22 23 24 25 26 27 28 29] [30 31 32 33 34 35 36 37 38 39] [40 41 42 43 44 45 46 47 48 49] [50 51 52 53 54 55 56 57 58 59] [60 61 62 63 64 65 66 67 68 69] [70 71 72 73 74 75 76 77 78 79] [80 81 82 83 84 85 86 87 88 89] [90 91 92 93 94 95 96 97 98 99]]
np.whereを使うと、条件に合う要素の列番号と行番号をarrayとして返します。
>>> import numpy as np >>> np.where(mat>50) (array([5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]), array([1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
さらに、条件に合わない要素に指定した値を入れることができる。
>>> np.where(mat>50,mat,0) array([[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 51, 52, 53, 54, 55, 56, 57, 58, 59], [60, 61, 62, 63, 64, 65, 66, 67, 68, 69], [70, 71, 72, 73, 74, 75, 76, 77, 78, 79], [80, 81, 82, 83, 84, 85, 86, 87, 88, 89], [90, 91, 92, 93, 94, 95, 96, 97, 98, 99]])
こうなると、np.where(mat>50 or mat<10)を試したくなるのが、人間の性です。しかし、これはうまく行きません。
numpy.whereを使って、複数の条件を指定する方法。
>>> np.where(np.logical_or(mat>50,mat<10),mat,0) array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 51, 52, 53, 54, 55, 56, 57, 58, 59], [60, 61, 62, 63, 64, 65, 66, 67, 68, 69], [70, 71, 72, 73, 74, 75, 76, 77, 78, 79], [80, 81, 82, 83, 84, 85, 86, 87, 88, 89], [90, 91, 92, 93, 94, 95, 96, 97, 98, 99]])
さらに、
np.logical_and() np.logical_not() np.logical_xor()
があります。
フィボナッチ数列を複数のスレッドを使って実行する。
Python3で並列計算をする場合、multiprocessingを使うことになると思います。このモジュールは、threadingの発展系でAPIが非常に似ているようです。今回は、multiprocessingを理解する前に、threadingモジュールを使ってフィボナッチ数列をスレッド化したいと思います。参考文献は文末に示しています。
このプログラムは、フィボナッチ数列の関数に複数の値を同時に与え、その答えを求めます。
#!/usr/bin/env python3 # coding :utf-8 import logging, threading ## --- logging --- ## エラーログをとるためのモジュール。 ## URL:http://docs.python.jp/3.4/library/logging.html from queue import Queue ## --- queue --- ## スレッド間で共有するデータを格納するためのモジュール。 ## URL:http://docs.python.jp/3.4/library/queue.html logger = logging.getLogger() logger.setLevel(logging.DEBUG) formatter = logging.Formatter('%(asctime)s - %(message)s') ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) ch.setFormatter(formatter) logger.addHandler(ch) fibo_dict = {} shared_queue = Queue() input_list = [3 ,10, 5, 7] queue_condition = threading.Condition() ## ある条件で、データの同期をするためのオブジェクト。 ## この場合は、プロセスやスレッドの生成をするため。 def fibonacci_task(condition): ## フィボナッチ数列をスレッドを生成させて、計算するための関数。 with condition: while shared_queue.empty(): logger.info("[%s] - waiting for elements in queue.." % threading.current_thread().name) condition.wait() ## shared_queueが埋まるまで待つ。 else: value = shared_queue.get() ## 実行されている各スレッドがshared_queueから要素を取得する。 ## fibo_dictから値を受け取り、フィボナッチ数列の計算が行われる。 a, b = 0, 1 for item in range(value): a, b = b, a+b fibo_dict[value] = a shared_queue.task_done() ## それぞれのスレッドが完了したか知るための関数。 logger.debug("[%s] - fibonacci of key [%d] with result [%d]" % (threading.current_thread().name, value, fibo_dict[value])) def queue_task(condition): ## shared_queueに要素が受け渡されているかを確認するための関数。 logging.debug('Stating queue_task...') with condition: for item in input_list: shared_queue.put(item) logging.debug("Notifying fibonacci_task threads that the queue is ready to consume..") condition.notifyAll() ## それぞれのスレッドが準備できているか知るための関数。 threads = [threading.Thread(daemon=True, target=fibonacci_task, args=(queue_condition,)) for i in range(4)] ## 4つのスレッドを生成。 [thread.start() for thread in threads] ## 4つのスレッドを実行。 ## 要素が渡されていないので、この場合はwaitしている。 prod = threading.Thread(name='queue_task_thread', daemon=True, target=queue_task, args=(queue_condition,)) prod.start() ## shared_queueにそれぞれの値をセットし、実行する。 [thread.join() for thread in threads] ## すべての子スレッドが終わる前にこのプログラムが終わらないようにする。
実行結果
2015-10-03 22:19:42,687 - [Thread-1] - waiting for elements in queue.. 2015-10-03 22:19:42,687 - [Thread-2] - waiting for elements in queue.. 2015-10-03 22:19:42,688 - [Thread-3] - waiting for elements in queue.. 2015-10-03 22:19:42,688 - [Thread-4] - waiting for elements in queue.. 2015-10-03 22:19:42,688 - Stating queue_task... 2015-10-03 22:19:42,688 - Notifying fibonacci_task threads that the queue is ready to consume.. 2015-10-03 22:19:42,688 - [Thread-1] - fibonacci of key [3] with result [2] 2015-10-03 22:19:42,689 - [Thread-2] - fibonacci of key [10] with result [55] 2015-10-03 22:19:42,689 - [Thread-3] - fibonacci of key [5] with result [5] 2015-10-03 22:19:42,689 - [Thread-4] - fibonacci of key [7] with result [13]
Parallel Programming With Python
- 作者: Jan Palach
- 出版社/メーカー: Packt Publishing
- 発売日: 2014/06/25
- メディア: ペーパーバック
- この商品を含むブログを見る
numpy.arrayによる2次元配列から任意の列を抽出する方法
2次元配列を扱っていると、ある列だけ取り出したいことはよくあることです。そんなときに、np.arrayを使いましょう。
対象と成る配列は以下のようになります。
mat =\ [[ 0 1 2 3 4 5 6 7 8 9] [10 11 12 13 14 15 16 17 18 19] [20 21 22 23 24 25 26 27 28 29] [30 31 32 33 34 35 36 37 38 39] [40 41 42 43 44 45 46 47 48 49] [50 51 52 53 54 55 56 57 58 59] [60 61 62 63 64 65 66 67 68 69] [70 71 72 73 74 75 76 77 78 79] [80 81 82 83 84 85 86 87 88 89] [90 91 92 93 94 95 96 97 98 99]]
まずは2列目だけを取り出したい場合。
mat[:,2]
出力
array([ 2, 12, 22, 32, 42, 52, 62, 72, 82, 92])
2列目を2次元配列で取り出す場合。
mat[:,2:3]
出力
array([[ 2], [12], [22], [32], [42], [52], [62], [72], [82], [92]])
奇数列のみを取り出したい場合。
mat[:,1::2]
出力
array([[ 1, 3, 5, 7, 9], [11, 13, 15, 17, 19], [21, 23, 25, 27, 29], [31, 33, 35, 37, 39], [41, 43, 45, 47, 49], [51, 53, 55, 57, 59], [61, 63, 65, 67, 69], [71, 73, 75, 77, 79], [81, 83, 85, 87, 89], [91, 93, 95, 97, 99]])
正直、ここまではpythonを知っている人ならば当たり前過ぎる話です。
任意の列を取り出したい場合。(1列目、7列目、8列目、8列目)
mat[:,np.array([0,6,7,7])]
出力
array([[ 0, 6, 7, 7], [10, 16, 17, 17], [20, 26, 27, 27], [30, 36, 37, 37], [40, 46, 47, 47], [50, 56, 57, 57], [60, 66, 67, 67], [70, 76, 77, 77], [80, 86, 87, 87], [90, 96, 97, 97]])
Indexの代わりにarrayを代入できるらへんが面白いですね。
UbuntuにおけるNginxデフォルトファイルの場所。
ある日、UbuntuでNginxをデプロイしようと、/etc/nginx/conf.d/defualt.confの中を書き換えました。いざ、デプロイしようとすると
sudo service nginx restart * Restarting nginx nginx [fail]
ダメだみたいです。エラーログ(/var/log/nginx/error.log)を見てみると
2015/09/30 11:36:36 [emerg] 9354#0: a duplicate default server for 0.0.0.0:80 in /etc/nginx/sites-enabled/default:21
80番のポートが使われていて、しかも/etc/nginx/sites-enabled/default:21に設定してあるようです。
ここで思い出したのですが、ubuntuでは仮想ホストを提供する構成があることを...。
つまり、/etc/nginx/site-availableにサーバーの設定をいくつも用意しておき、/etc/nginx/sites-enabled/にその中のシンボリックリンクを貼ればいつでもサーバーの設定を簡単に変えることが出来るのです。
早速、/etc/nginx/site-available/に/etc/nginx/conf.d/defualt.confで書いた設定を移し、/etc/nginx/sites-enabled/defaultを消し、新たにシンボリックリンクを貼り直しました。
平衡統計力学の本の紹介。無料‼︎
統計力学を復習しようと思い、本を漁ってました。平衡論を学ぶなら、これ一冊?でいいんじゃないかと思うほど丁寧で幅広く説明している本を発見しました。しかも無料!!!。なぜ、無料なのかと言うと講義のレジュメだからです。下記のURLからLECUTUREにアクセスするとゲット出来ます。まだ、熟読していないのでパッとみた感じの印象です。ご了承ください。
https://physics.ucsd.edu/students/courses/spring2010/physics210a/
お金がある人は以下の本でしょう。安くて安心のDoverです。
An Introduction to Statistical Thermodynamics (Dover Books on Physics)
- 作者: Terrell L. Hill,Physics
- 出版社/メーカー: Dover Publications
- 発売日: 1987/01/01
- メディア: ペーパーバック
- 購入: 1人 クリック: 1回
- この商品を含むブログを見る
さらにお金がある人は、
Introduction to Modern Statistical Mechanics
- 作者: David Chandler
- 出版社/メーカー: Oxford Univ Pr (Sd)
- 発売日: 1987/09/17
- メディア: ペーパーバック
- この商品を含むブログ (1件) を見る
Python中級者向けで気になる本の紹介。
自分のPythonの知識が初級から中級の間にあると思うので、気になる本を紹介したいと思います。(もちろん、私は読みません。お金がありません。こういう本があるということを知っていることが重要だと思います。)とりあえず、自分が考える初級、中級、上級とは何かを説明したいと思います。もちろん、人によって考え方が異なるので、私なりの考え方です。
プログラミングの概念は、どのようなプログラミング言語も普遍だと思います。どのような言語でも中級まで行けば身になると思います。しかし、どのようなプログラミング言語もいずれは廃れるでしょう。あるプログラミング言語に固執し過ぎるのもやめましょう。
- 初級:Pythonでプログラムを書くことができる。
- 中級:Pythonの得意な部分と不得意な部分を理解し、不得意な部分は他の言語を使用してプログラムをかける。
- 上級:どのようなプログラムもPythonで書き換えることができ、最高のパフォーマンスを引き出すことができる。
- CやC++でパッケージを作成し、性能に特化したパッケージを提供できるレベルを指します。
上級は理想です。中級を目指したいところですね。
Effective Python: 59 Specific Ways to Write Better Python (Effective Software Development Series)
- 作者: Brett Slatkin
- 出版社/メーカー: Addison-Wesley Professional
- 発売日: 2015/03/08
- メディア: ペーパーバック
- この商品を含むブログ (1件) を見る
- 作者: David Beazley,Brian K. Jones
- 出版社/メーカー: Oreilly & Associates Inc
- 発売日: 2013/05/29
- メディア: ペーパーバック
- この商品を含むブログを見る
High Performance Python: Practical Performant Programming for Humans
- 作者: Micha Gorelick,Ian Ozsvald
- 出版社/メーカー: Oreilly & Associates Inc
- 発売日: 2014/09/20
- メディア: ペーパーバック
- この商品を含むブログを見る
- 作者: Luciano Ramalho
- 出版社/メーカー: Oreilly & Associates Inc
- 発売日: 2015/08/20
- メディア: ペーパーバック
- この商品を含むブログを見る
Twisted Network Programming Essentials
- 作者: Abe Fettig
- 出版社/メーカー: Oreilly & Associates Inc
- 発売日: 2005/10/01
- メディア: ペーパーバック
- 購入: 1人 クリック: 24回
- この商品を含むブログ (8件) を見る
Test-Driven Development with Python
- 作者: Harry Percival
- 出版社/メーカー: Oreilly & Associates Inc
- 発売日: 2014/06/29
- メディア: ペーパーバック
- この商品を含むブログを見る
- 作者: Julia Elman,Mark Lavin
- 出版社/メーカー: Oreilly & Associates Inc
- 発売日: 2014/11/13
- メディア: ペーパーバック
- この商品を含むブログを見る
- 作者: TJ O'Connor
- 出版社/メーカー: Syngress
- 発売日: 2012/12/28
- メディア: Kindle版
- この商品を含むブログを見る
Learning Python Design Patterns
- 作者: Gennadiy Zlobin
- 出版社/メーカー: Packt Publishing
- 発売日: 2013/11/25
- メディア: ペーパーバック
- この商品を含むブログを見る
第5回:Pythonでネットワークプログラミング(TCPプロキシ)
pythonによるプロキシのプログラムです。ほぼ写経ですので、詳しく知りたい方は、参考文献をご参考ください。このプログラムは、プロキシの役割を通りにホスト←→プログラム←→クライアントを実現します。
#!/usr/bin/env python import sys import socket import threading def server_loop(local_host,local_port,remote_host,remote_port,receive_first): server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) try: server.bind((local_host,local_port)) except: print "[!!]Failed to listen on %s:%d" % (local_host,local_port) sys.exit(0) server.listen(5) print "[!!]Listening on %s:%d" % (local_host,local_port) while True: client_socket, addr = server.accept() print "[==>] Received incoming connection from %s:%d" % (addr[0],addr[1]) proxy_thread = threading.Thread(target=proxy_handler,args=(client_socket,remote_host,remote_port,recevie_first)) proxy_thread.start() def main(): if len(sys.argv[1:]) != 5: print "Usage: ./tcp_proxy.py [localhost] [localport] [remotehost] [remoteport] [recive_fisrt]" sys.exit(0) local_host = sys.argv[1] local_port = int(sys.argv[2]) remote_host = sys.argv[3] remote_port = int(sys.argv[4]) receive_first = sys.argv[5] if "True" in receive_first: receive_first = True else: receive_first = False server_loop(local_host,local_port,remote_host,remote_port,receive_first) def proxy_handler(client_socket,remote_host,remote_port,recive_fisrt): remote_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) remote_socket.connect((remote_host,remote_port)) if recevie_first: remote_buffer = receive_from(remote_socket) hexdump(remote_buffer) remote_buffer = response_handler(remote_buffer) if len(remote_buffer): print "[<==] Sending %d bytes to localhost." % len(remote_buffer) client_socket.send(remote_buffer) while True: local_buffer = receive_from(client_socket) if len(local_buffer): print "[==>] Received %d bytes from localhost." % len(local_buffer) hexdump(local_buffer) #パケット書き換えの時に使用 local_buffer = request_handler(local_buffer) remote_socket.send(local_buffer) print "[==>] Sent to remote." remote_buffer = receive_from(remote_socket) if len(remote_buffer): print "[==>] Received %d bytes from remote." % len(remote_buffer) hexdump(remote_buffer) #パケット書き換えの時に使用 remote_buffer = response_handler(remote_buffer) #ローカルにソケットを送信する client_socket.send(remote_buffer) print "[==>] Sent to localhost." #データがないときに、コネクションを閉じる。 if not len(local_buffer) or not len(remote_buffer): client_socket.close() remote_socket.close() print "[*] No more data. Closing connections." break #16進数に変換する。 def hexdump(src,length=16): result = [] digits = 4 if isinstance(src, unicode) else 2 for i in xrange(0, len(src), length): s = src[i:i+length] hexa = b' '.join(["%0*X" % (digits, ord(x)) for x in s]) text = b''.join([x if 0x20 <= ord(x) < 0x7F else b'.' for x in s]) result.append( b"%04X %-*s %s" % (i,length*(digits + 1 ),hexa,text)) print b'\n',join(result) def receive_from(connection): buffer = "" #タイムアウト時間を2秒にセット conecction.settimeout(2) try: while True: data = connection.recv(4096) if not data: break buffer += data except: pass return buffer #リモートに送るパケットの書き換え用 def request_handler(buffer): return buffer #ローカルに来るパケットの書き換え用 def response_handler(buffer): return buffer main()
第4回:Pythonでネットワークプログラミング(Netcat的なものを実装)
そもそも、Netcaってなんなの?ということで、Wikipediaへ。どうやら、TCPやUDPのパケットを読み書きできるコマンドラインツールらしい...。とりあえず、本で紹介されているので実装してみましょう。紹介したプログラムは、ファイルのアップロード、コマンドの実行をすることができます。sshとscpの非常に簡単版です。もちろん暗号化されていないのでお遊びだと考えてください。参考としている本とは、多少コードが違いますので、元ネタを知りたい方は参考文献へ。ここで力尽きました...。残っているタイトルは後日作成します。
Black Hat Python: Python Programming for Hackers and Pentesters
- 作者: Justin Seitz
- 出版社/メーカー: No Starch Pr
- 発売日: 2014/12/14
- メディア: ペーパーバック
- この商品を含むブログを見る
Netcat的なものを実装
#! /usr/bin/env python # coding:utf-8 # netcat.py import sys import socket from optparse import OptionParser import threading import subprocess listen = False command = False upload = False execute = '' target = '' upload_destination = '' port = 0 def usage(): """オプションの解析""" """サーバー側での実行例(コマンドの受付):netcat.py -l -p 5555 -c """ """クライアント側での実行例(コマンドの受け渡し):netcat.py -t 0.0.0.0 -p 5555""" """Fileのアップロード,-u""" description="Examples:\n\r\ netcat.py -t 192.168.0.1 -p 5555 -l -c\n\ netcat.py -t 192.168.0.1 -p 5555 -l -c -u=c:\\target.ext\n\ netcat.py -t 192.168.0.1 -p 5555 -l -c -e=\"cat /etc/passwd\"\n\ echo 'ABCDEFGHI' | netcat.py -t 192.168.0.1 -p 135\n\ " parser=OptionParser(usage='%prog [-c] [-l] [-u] [-e] [-t] [-p]',epilog=description) parser.add_option('-c','--commandshell',help='initialize a command shell',default=False,action='store_true') parser.add_option('-u','--upload',help='upon receiving connection upload a file and write to [destination]',default='') parser.add_option('-l','--listen',help='listen on [host]:[port] for incoming connections',default=False,action='store_true') parser.add_option('-e','--execute',help='ececute the fiven file upon receiving a command shell',default='') parser.add_option('-t','--target',help='',default='') parser.add_option('-p','--port',help='',type=int) opt,args=parser.parse_args() global listen global port global execute global command global upload_destination global target listen = opt.listen command = opt.commandshell upload = opt.upload execute = opt.execute target = opt.target upload_destination = opt.upload port = opt.port def main(): global listen global port global execute global command global upload_destination global target usage() if not listen and len(target) and port > 0: print ":Client mode" buffer = sys.stdin.readline() client_sender(buffer) if listen: print ":Server mode" server_loop() def client_sender(buffer): client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) try: client.connect((target,port)) #コネクションの確率 if len(buffer): client.send(buffer) while True: recv_len = 1 response = '' while recv_len: buf_size = 4096 data = client.recv(buf_size) recv_len = len(data) response += data if recv_len < buf_size: break print response, #クライアント側で実行した結果を受け取り、表示する。 buffer = raw_input('') #クライアントの要求の受付を継続する。 buffer += '\n' client.send(buffer) except: print '[*] Exception! Exiting.' client.close() def server_loop(): global target global port if not len(target): target = '0.0.0.0' server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind((target,port)) server.listen(5) while True: client_socket, addr = server.accept() print addr client_thread = threading.Thread(target=client_handler,args=(client_socket,)) #threadingに関しては過去の記事を参照してください。 client_thread.start() def run_command(command): command = command.rstrip() #改行の削除 try: output = subprocess.check_output(command,stderr=subprocess.STDOUT,shell=True) #コマンドの実行を結果をoutputに保存する。 #subprocessはpythonの標準ライブラリなので、勉強する価値はあります。公式のドキュメントが分かりやすいです。 except: output = 'Failed to execute command.\n\r' return output def client_handler(client_socket): global upload global execute global command if len(upload_destination): file_buffe = '' while True: buf_size = 1024 data = client_socket.recv(buf_size) if not data: break else: file_buffer += data try: file_descriptor = open(upload_destination,'wb') file_descriptor.write(file_buffer) file_descriptor.close() client_socket.send('Successfully saved file file to %s\r\n' % upload_destination) except: client_socket.send('Failed to save file file to %s\r\n' % upload_destination) if len(execute): output = run_command(execute) client_socket.send(output) if command: #flag -c が設定されているときにcomandが実行される。 while True: client_socket.send('<BF?:#>') cmd_buffer = '' while '\n' not in cmd_buffer: cmd_buffer += client_socket.recv(1024) response = run_command(cmd_buffer) client_socket.send(response) main()
第3回:Pythonでネットワークプログラミング(TCPサーバーを立てる)
TCPを使った通信では、クライアントはコネクションの確立を行うことが重要でした。socketの作成は慣れです。これは、C言語と非常に似ています。Pythonでネットワークプログラミングを勉強しておけば、C言語で勉強するときにも役に立つはずです。そもそも、ネットワークプログラミングを勉強をする必要があるかどうかはここでは問いません!!!
TCPサーバーを立てる
まずはサーバー側のプログラムから
#! /usr/bin/env python # coding:utf-8 # tcp_server import socket import threading bind_ip = '0.0.0.0' bind_port = 9999 server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #socket.AF_INETでip4を使うことを指定。socket.SOCK_STREAMでTCPを使うことを指定。 server.bind((bind_ip,bind_port)) #自分のIPアドレスとportを設定する。 #相手のIPアドレスとportを設定する場合は、connectを使うと考えてよい。 server.listen(5) #コネクションの最大保存数を設定する。 print '[*]Listening on %s:%d' % (bind_ip,bind_port) def handle_client(client_socket): bufsize=1024 request = client_socket.recv(bufsize) print '[*] Recived: %s' % request client_socket.send("Hallo Client!!!\n") client_socket.close() while True: client,addr = server.accept() #bind済みのソケットから、新たなソケットと接続先のアドレスを返す。 print '[*] Accepted connectoin from: %s:%d' % (addr[0],addr[1]) client_handler = threading.Thread(target=handle_client,args=(client,)) # threadingを使って、スレッドを生成する。マルチコアに対応させたい場合は,multiprocessingを使えば良い。 # targetは呼び出す関数(オブジェクト)を指定し、argsはその引数を指定している。 client_handler.start() # 処理を開始する。
クライアント側のプログラム。第1回のプログラムを書き換えてやれば、終了です。
#! /usr/bin/env python # coding:utf-8 # tcp_client import socket target_url='0.0.0.0' target_port=9999 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #socket.AF_INETでip4を使うことを指定。socket.SOCK_STREAMでTCPを使うことを指定。 s.connect((target_url,target_port)) #コネクションを確立する。 s.send('Hello Server!!!\n') response = s.recv(4096) print response
ターミナルを2つ開いて、実行してやれば、通信できます。