Remind-You Part2. setup.py打包代碼, socket通訊

插線板的英文是socket噢!!!

內容

  • 完成dict plugin的服務端啟動socket監聽
  • 將Project使用setuptools進行打包
  • 生成客戶端程序save_word
  • 使用argparse解析命令行參數

倉庫代碼中的day2分支 https://github.com/bymzy/remind-you/tree/day2

效果

使用python setup.py bdist_rpm生成rpm包,然后使用rpm -ivh remind_you-0.1-1.noarch.rpm安裝。python庫目錄中將會安裝remind_you包,同時會在系統目錄中增加可執行文件save_word。
啟動dict plugin服務端:

服務端啟動后,dict plugin監聽在目標端口

執行save_word命令

save_word命令執行

可以看到,客戶端執行save_word命令后,服務端能夠收到客戶端的消息。

使用的庫

setuptools

使用setuptools對整個代碼打包(個人比較喜歡打成rpm包python setup.py bdist_rpm,方便安裝刪除)。同時,使用setuptools生成可執行文件(save_word)。倉庫最上層目錄下的setup.py文件記錄了配置信息,代碼如下:

from setuptools import setup, find_packages

setup(
    name = 'remind_you',
    version = '0.1',
    packages = find_packages(),
    package_data = { 
        '':['*.conf']
    },  
    data_files = [('/etc/', ['remind_you/plugins/scheduler.conf'])],
    author = 'mingzhengying',
    description = 'remind you something!!!',
    entry_points = { 
        'console_scripts': [
            'save_word = remind_you.cmds:save_word_cmd',
            ]   
    }   
)

setuptools是distutils的加強版本,上述配置文件中重要部分說明如下

  • packages = find_packages() 表示在當前setup.py同等目錄下尋找源文件
  • package_data 部分表示將所有的包目錄下*.conf文件進行打包
  • data_files用來將配置文件,安裝到/etc目錄下
  • console_scripts用來生成命令行執行程序,程序的執行入口是remind_you.cmds.save_word_cmd這個函數

socket, argparse

使用最簡單的socket阻塞模型。dict plugin讀取配置文件,然后監聽在特定的端口上。客戶端命令運行后同樣讀取配置文件,連接服務器端。

dict plugin服務端代碼如下:

def generate_request(_word, _trans):
    trans = pack_int(_trans)
    word = pack_str(_word)
    totalLen = 4 + len(trans) + len(word)
    return pack_int(totalLen) + trans + word

def recv_request(cl):
    tmp = recv_len(cl, 4)
    wordLen = unpack_int(tmp)
    data = recv_len(cl, wordLen)
    trans = unpack_int(data[0:4])
    word = unpack_str(data[4:])
    return word, trans

def run(args):
    print 'my pid is: %u , %s ' % (os.getpid(), args)
    port = args.get('port')
    ip = args.get('ip')
    dbPath = args.get('db')

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind((ip, port))
    sock.listen(5)

    while True:
        cl, addr = sock.accept()
        word, trans = recv_request(cl)
        print 'receive word %s , need trans %d: ' % (word, trans)
        cl.close()

run方法作為dict plugin進程的主方法,會被主進程啟動,然后監聽在某個端口上。后續有客戶端連接后,從客戶端的輸入中解析出請求的word, trans,分別表示單詞,和是否返回翻譯信息。目前的實現中,服務端僅僅會將得到的信息打印出來,然后斷開連接等待下個請求。


客戶端代碼如下:

cmds.py

from plugins import dict_cmd

def save_word_cmd():
    dict_cmd.run()

setup.py配置中,生成的客戶端命令save_word最終會調用save_word_cmd,進而調用dict_cmd.run()方法。

dict_cmd.py

CONF = '/etc/scheduler.conf'
PLUGIN_NAME = 'dict'

def get_ip_port():
    with open(CONF) as f:
        data = f.read()

    di = json.loads(data)
    for plugin in di.get('plugins', []):
        if plugin.get('name') == PLUGIN_NAME:
            return plugin.get('args').get('ip'), plugin.get('args').get('port')
    return None, None

def parse_cmd_args():
    args_parser = argparse.ArgumentParser()
    args_parser.add_argument("-w", "--word", type=str, required=True);
    args_parser.add_argument('-t', '--trans', action='store_true', default=False);

    args = args_parser.parse_args()
    #use vars to get a dict
    #print vars(args), type(vars(args))
    return args.word, args.trans

def run():
    ip, port = get_ip_port()
    word, trans = parse_cmd_args()
    s = connect_ip_port(ip, port)
    if s is None:
        print 'connect to server %s:%d failed!!!' % (ip, port)
        sys.exit(1)
    req = generate_request(word, trans)
    send_data(s, req)

客戶端的save_word命令,調用dict_cmd.run()方法后會做如下事情:

  • 讀取配置文件得到服務端的ip,port
  • 解析命令行參數
  • 生成請求req數據
  • 調用send_data將req數據發送給服務端

send_data, connect_ip_port等函數在util.py中定義

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 內容 1. 將Part2中接收到的客戶端請求單詞,存入sqlite數據庫中。 2. 將主程序打包成命令remind...
    帶不動明少閱讀 442評論 0 3
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,886評論 18 139
  • supervisor 是由python語言編寫、基于linux操作系統的一款服務器管理工具,用以監控服務器的運行,...
    每次哭都笑著奔跑閱讀 6,323評論 6 14
  • 人們喜歡看十字繡,從前面看特別好看,完美無暇。但是后面你看不見的地方,亂線交錯,丑陋無比。這才是最真實的人,Ta從...
    一個人的春夏秋冬閱讀 417評論 6 6
  • 總會想起若干年前,冬日里爺爺家的磚瓦房上升起的裊裊炊煙,仿佛已成了春節的符號,刻印在我深深的記憶里。 彼時尚小,那...
    紙人貓閱讀 379評論 0 1