おいも貴婦人ブログ

生物系博士課程満期退学をしたAIエンジニアのブログ。

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

Parallel Programming With Python

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

Parallel Programming With Python

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)

An Introduction to Statistical Thermodynamics (Dover Books on Physics)

さらにお金がある人は、

Introduction to Modern Statistical Mechanics

Introduction to Modern Statistical Mechanics

Python中級者向けで気になる本の紹介。

自分のPythonの知識が初級から中級の間にあると思うので、気になる本を紹介したいと思います。(もちろん、私は読みません。お金がありません。こういう本があるということを知っていることが重要だと思います。)とりあえず、自分が考える初級、中級、上級とは何かを説明したいと思います。もちろん、人によって考え方が異なるので、私なりの考え方です。
プログラミングの概念は、どのようなプログラミング言語も普遍だと思います。どのような言語でも中級まで行けば身になると思います。しかし、どのようなプログラミング言語もいずれは廃れるでしょう。あるプログラミング言語に固執し過ぎるのもやめましょう。

  • 初級:Pythonでプログラムを書くことができる。
  • 中級:Pythonの得意な部分と不得意な部分を理解し、不得意な部分は他の言語を使用してプログラムをかける。
    • 車輪の再開発を行うのではなくて、既存のライブラリーを利用して、特定の分野に優れているライブラリー持っている言語を使用すると言う意味です。
    • たとえば、フルスタックのwebフレームワークをみてみると、pythonではDjangoやFlaskになると思います。しかし、パーフォマンスやシェアをみるとRuby on Railsに軍配があがると言えるでしょう。そのようなときは、素直にRailsを使うことができるレベルを指します。
  • 上級:どのようなプログラムもPythonで書き換えることができ、最高のパフォーマンスを引き出すことができる。
    • CやC++でパッケージを作成し、性能に特化したパッケージを提供できるレベルを指します。

上級は理想です。中級を目指したいところですね。

Effective Python: 59 Specific Ways to Write Better Python (Effective Software Development Series)

Effective Python: 59 Specific Ways to Write Better Python (Effective Software Development Series)

Python Cookbook

Python Cookbook

High Performance Python: Practical Performant Programming for Humans

High Performance Python: Practical Performant Programming for Humans

Fluent Python

Fluent Python

Twisted Network Programming Essentials

Twisted Network Programming Essentials

Test-Driven Development with Python

Test-Driven Development with Python

Lightweight Django

Lightweight Django

Learning Python Design Patterns

Learning Python Design Patterns

第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へ。どうやら、TCPUDPのパケットを読み書きできるコマンドラインツールらしい...。とりあえず、本で紹介されているので実装してみましょう。紹介したプログラムは、ファイルのアップロード、コマンドの実行をすることができます。sshとscpの非常に簡単版です。もちろん暗号化されていないのでお遊びだと考えてください。参考としている本とは、多少コードが違いますので、元ネタを知りたい方は参考文献へ。ここで力尽きました...。残っているタイトルは後日作成します。

Black Hat Python: Python Programming for Hackers and Pentesters

Black Hat Python: Python Programming for Hackers and Pentesters

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つ開いて、実行してやれば、通信できます。