教你分分鐘開發一個屬於自己的python模組(一)——能夠直接在瀏覽器列印的方法,python模組
曾經,用慣了python print命令的人,驚歎於python文法的精簡;後來,用過了tornado、django等web開發架構,不得不佩服當初開發這些架構的人們。於是,我們開始使用它們的架構==》一個被重複了無數次的配置。那麼問題來了,如果我很多次的完成某個領域的類似問題,我需要每次都去重複的配置嗎?偶然間,我在想,能否在它們的架構上繼續精簡,以在某種用途上實現更加高效的開發。web架構的使用,包含server端和browser端。本次改裝採用tornado架構。
首先,我們從接觸python第一天的print(“Helloworld!”)開始。
乾貨開始:
首先我們來看一段精簡的tornado代碼:
import tornado.ioloopimport tornado.web class MainHandler(tornado.web.RequestHandler): def get(self): self.write("Hello, world") application = tornado.web.Application([ (r"/index", MainHandler),]) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()
上述代碼實現了在瀏覽器端輸出hello,world!從上到下各部分的功能依次是:模組匯入、業務處理類、路由映射、服務端開啟。
本博文詳細介紹模組的改裝,更多tornado基礎內容,詳見下面連結:
上述代碼雖然實現了在瀏覽器的輸出內容,但是有很多不足之處:
- 每次列印一個東西,使用者都需要寫那麼多代碼
- 只能支援字串列印,不能支援字典、列表、元組等常見資料結構
我們知道,python的print用法很簡單,只需要我們將需要列印的東西放在print內部,即可用一句話列印出我們想要的結果來。那麼問題來了,有沒有一種簡單的方法能夠類似print使用一句話在瀏覽器上列印出我們想要的任何資料結構?
答案當然是:有。沒錯,你沒有看錯,接下來,博主來帶你一步一步實現這個神奇的功能。
模組匯入:
import tornado.ioloopimport tornado.webimport json
和之前有所不同的是,我們增加了json模組,聰明你你應該已經猜到了,博主是想通過json實現對不同資料結構的支援,是的啊,沒錯!有人說,這不算什麼,我也會,好,別走,繼續往下看!更多精彩,詳見下文!
解決思路:
事實上,解決這個問題,其實很簡單,核心問題就是如何通過傳參方式,將使用者需要列印的資料傳遞給self.write。
要解決這個問題,我們需要指定,tornado架構哪些地方可以進行傳參,我們再來看一下tornado代碼:
import tornado.ioloopimport tornado.web class MainHandler(tornado.web.RequestHandler): def get(self): self.write("Hello, world") application = tornado.web.Application([ (r"/index", MainHandler),]) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()
我們採用由內向外的分析方法:
- 首先是self.write("Hello, world"),我們希望實現的結果是self.write(arg),arg代表使用者傳入的參數。而這個arg又要從哪裡傳入呢?包著它的是get方法,我們知道http協議的get方法可以通過在瀏覽器的url上通過問號加索引值對的方式傳入資料,可是難道使用者每次列印資料都去瀏覽器的url輸入嗎?這明顯不合理。因此get方法傳參是行不通的。
- 接下來往外是業務處理類MainHandler,它能傳參嗎?我們知道類是可以通過init方法進行傳參的,每次對類進行執行個體化的時候進行傳參即可,我們需要自己定義個init方法並繼承父類的init方法嗎?可是問題是,這個MainHandler到底是在哪裡進行執行個體化的,我們又需要在哪裡對其進行傳參呢?這裡就到了tornado的源碼部分,可是源碼豈能隨便去改,因此init方法傳參也不合理。
- 為了遵循對源碼封閉,對擴充開放的原則,其實tornado源碼中已經為我們預留了位置,這就是傳說中的initialize方法,也就是人們所說的“鉤子”。
initialize方法如何使用呢?
首先需要自己定義一個類,用於複寫源碼中的initialize方法,因為源碼中initialize方法其實什麼事也沒幹。
class BaseHandler(tornado.web.RequestHandler): def initialize(self,arg): self.arg=arg
在這裡,我們為initialize方法傳入了參數arg,並給類增加屬性self.arg=arg,這樣做的目的是為了繼承它的子類能夠使用這個參數,這就是物件導向的封裝,參數傳遞一次,這個類的子類的所有方法都是可以使用的。沒錯,聰明的你又發現了,等會如果我們的MainHandler類只要繼承了BaseHandler類,那麼MainHandler類的get方法中,就可以使用參數self.arg。下面就是MainHandler類的改裝。
class MainHandler(BaseHandler): def get(self): self.write(self.arg)
做到這裡,你可能已經發現:好吧,initialize方法傳參我會了,可是使用者輸入的參數又是如何傳入initialize方法呢?
我們發現唯一跟MainHandler類有關的,就是路由映射了,它是一個元組,元組第0個元素是正則匹配,第一個元素是業務處理類的類名,於是博主就想,這裡能否接收第三個參數呢?能否進行傳參呢?來看一眼路由映射:
application = tornado.web.Application([ (r"/index", MainHandler, ), ])
經過博主對Application類源碼進行分析,果然,它是支援傳第三個參數的:
源碼:
源碼中spec即每一個元組。更多源碼問題,歡迎讀者在下方評論,與博主進行探討。經過博主多方諮詢探討,最終得出結論,第三個參數支援字典格式進行傳遞(源碼中是**kwargs)。
路由映射改裝代碼:
application = tornado.web.Application([ (r"/index", MainHandler, dict(arg=json.dumps(request))), ])
同時,為了支援常見資料結構,博主採用json進行序列化資料。
以上就是整個改裝流程,下面附整體代碼模組和該模組的使用方法。
import tornado.ioloopimport tornado.webimport jsonclass BaseHandler(tornado.web.RequestHandler): def initialize(self,arg): self.arg=argclass MainHandler(BaseHandler): def get(self): self.write(self.arg)def print_to_browser(request,port=8888): application = tornado.web.Application([ (r"/", MainHandler, dict(arg=json.dumps(request))), ]) application.listen(port) tornado.ioloop.IOLoop.instance().start()
上述模組是博主原創,封裝了tornado路由映射、服務端開啟,支援傳參,第一個參數即需要列印的內容,第二個參數為選擇性參數,預設連接埠8888,如果使用者有傳遞,則以使用者輸入的參數為準。
鑒於博主有文章被多家網站盜用,鑒於此,原諒博主在此插播聲明一條:本博文為博主原創,轉賬請註明原文連結:http://www.cnblogs.com/wanghzh/p/5869336.html,謝謝合作!
模組使用:
#!/usr/bin/env python# -*- coding: utf-8 -*-from my.mytornado import print_to_browser #匯入上述模組print_to_browser([1,2,3,4,])
結果樣本:
上述使用方法是不是同python內建的print一樣簡單呢,支援字串、字典、列表、元組等資料結構。預設網域名稱:127.0.0.1,預設連接埠:8888。使用者只需開啟瀏覽器用戶端即可(127.0.0.1:8888)。
如果您覺得本文對您有參考價值,,歡迎幫博主點下文章下方的推薦,非常謝謝!