{"id":8688,"date":"2016-03-27T17:20:25","date_gmt":"2016-03-27T22:20:25","guid":{"rendered":"httpss:\/\/www.powenko.com\/wordpress\/?p=8688"},"modified":"2016-03-27T17:20:25","modified_gmt":"2016-03-27T22:20:25","slug":"%e5%bb%ba%e7%ab%8b%e4%b8%80%e5%80%8b-web-server-%e5%92%8c-%e8%a6%96%e7%aa%97%e7%9a%84python-%e7%a8%8b%e5%bc%8f","status":"publish","type":"post","link":"https:\/\/www.powenko.com\/wordpress\/?p=8688","title":{"rendered":"\u5efa\u7acb\u4e00\u500b Web Server \u548c  \u8996\u7a97\u7684Python \u7a0b\u5f0f"},"content":{"rendered":"<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n#    Copyright 2015 Powen Ko &lt;powenko@gmail.com&gt;\r\n#\r\n#    This program is free software: you can redistribute it and\/or modify\r\n#    it under the terms of the GNU General Public License as published by\r\n#    the Free Software Foundation, either version 3 of the License, or\r\n#    (at your option) any later version.\r\n#\r\n#    This program is distributed in the hope that it will be useful,\r\n#    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n#    GNU General Public License for more details.\r\n#\r\n#    You should have received a copy of the GNU General Public License\r\n#    along with this program.  If not, see &lt;httpss:\/\/www.gnu.org\/licenses\/&gt;.\r\n \r\nimport Queue\r\nimport SocketServer\r\nimport socket\r\nimport sys\r\nimport logging\r\nimport threading\r\nimport Tkinter as tk\r\nfrom os import curdir, sep\r\nimport os\r\nfrom ScrolledText import ScrolledText\r\nfrom BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer\r\nimport webbrowser\r\n\r\n\r\npathname=os.path.dirname(__file__)\r\n# .py program path location\r\nblocklydir = &quot;%s\/blockly&quot; % curdir  \r\navrpath = &quot;%s\/avr\/code\/&quot; % curdir \r\nsketchbookdir = os.path.expanduser('~\/blockly-sketchbook')\r\npathdiff=&quot;&quot;\r\nif (pathname.find(&quot;icblock.app&quot;)&gt;1):\r\n  pathdiff=&quot;..\/..\/..\/&quot;  \r\n  blocklydir = pathdiff+&quot;blockly&quot;  \r\n  avrpath =pathdiff+avrpath\r\n\r\nmimes = {\r\n    '.html': 'text\/html',\r\n    '.js': 'application\/javascript',\r\n    '.css': 'text\/css',\r\n    '.wav': 'audio\/vnd.wave',\r\n    '.cur': 'image\/vnd.microsoft.icon',\r\n    '.png': 'image\/png',\r\n    '.ico': 'image\/vnd.microsoft.icon'\r\n}\r\n\r\n\r\n#file_to_copy = &#x5B;'build.sh', 'pins_arduino.c', 'pins_arduino.h', 'servo.c', 'servo.h', 'servo_asm.S', 'wiring.h', 'wiring_digital.c', 'avr-thread.h', 'libavr-thread.a']\r\n#dst = tempfile.mkdtemp('', 'blockly-avr-')\r\ntarget=&quot;arduino&quot;\r\n\r\n\r\ntry:\r\n    os.mkdir(sketchbookdir)\r\nexcept OSError:\r\n    pass\r\n\r\ndef build_file_list():\r\n    global sketchbookdir\r\n    list = sketchbookdir;\r\n    dirList=os.listdir(sketchbookdir)\r\n    for fname in dirList:\r\n        list = list + '&lt;li&gt;&lt;a href=&quot;#&quot; onclick=&quot;do_action(\\'%s\\'); return false;&quot;&gt;%s&lt;\/a&gt;&lt;\/li&gt;\\n' % (fname, fname)\r\n    return list\r\n\r\nclass MyHandler(BaseHTTPRequestHandler):\r\n\r\n    def do_GET(self):\r\n        try:\r\n            if self.path == '\/':\r\n                self.send_response(301)\r\n                self.send_header(&quot;Location&quot;, 'demos\/code\/index.html')\r\n                self.end_headers()\r\n                return\r\n            filell,ext = os.path.splitext(self.path)\r\n            mime = mimes&#x5B;ext]\r\n\r\n            f = open(blocklydir + sep + self.path) #self.path has \/test.html\r\n#note that this potentially makes every file on your computer readable by the internet\r\n\r\n            self.send_response(200)\r\n            self.send_header('Content-type', mime)\r\n            self.end_headers()\r\n            self.wfile.write(f.read())\r\n            f.close()\r\n            return\r\n\r\n                \r\n        except IOError, KeyError:\r\n            self.send_error(404,'File Not Found: %s, %s ,  %s' % (self.path,sketchbookdir,os.path.dirname(__file__)     ) )\r\n    \r\n\r\n\r\n\r\n    def do_POST(self):\r\n       \r\n    \r\n\r\n\r\n\r\nclass QueueLogger(logging.Handler):\r\n    def __init__(self, queue):\r\n        logging.Handler.__init__(self)\r\n        self.queue = queue\r\n \r\n    # write in the queue\r\n    def emit(self, record):\r\n        self.queue.put(self.format(record).rstrip('\\n') + '\\n')\r\n \r\nclass LoggedUDPServer(SocketServer.ThreadingMixIn, SocketServer.UDPServer):\r\n    def __init__(self, server_address, RequestHandlerClass, logger):\r\n        # SocketServer.UDPServer.__init__(self, server_address, RequestHandlerClass)\r\n        # Add the queue logger\r\n        self.logger = logger\r\n \r\nclass UDPHandler(SocketServer.BaseRequestHandler):\r\n    def handle(self):\r\n        # Queue logger is un under the self.server object\r\n        self.server.logger.debug(self.request&#x5B;0])\r\n \r\nclass MainApplication:\r\n    def __init__(self, root, log_level, ip, port ):\r\n        self.root = root\r\n        self.log_level = log_level\r\n        self.ip = ip\r\n        self.port = port\r\n        self.root.columnconfigure(0, weight=1)\r\n        self.root.rowconfigure(0, weight=1)\r\n \r\n        # 2 rows: firts with settings, second with registrar data\r\n        self.main_frame = tk.Frame(self.root)\r\n        # Commands row doesn't expands\r\n        self.main_frame.rowconfigure(0, weight=0)\r\n        # Logs row will grow\r\n        self.main_frame.rowconfigure(1, weight=1)\r\n        # Main fram can enlarge\r\n        self.main_frame.columnconfigure(0, weight=1)\r\n        self.main_frame.columnconfigure(1, weight=1)\r\n        self.main_frame.grid(row=0, column=0, sticky=tk.NSEW)\r\n \r\n        # Run\/Stop button\r\n        self.control_button = tk.Button(self.main_frame, text=&quot;Run Server&quot;, command=self.run_server)\r\n        self.control_button.grid(row=0, column=0, sticky=tk.N)\r\n \r\n        # Clear button\r\n        self.clear_button = tk.Button(self.main_frame, text=&quot;Clear Log&quot;, command=self.clear_log)\r\n        self.clear_button.grid(row=0, column=1, sticky=tk.N)\r\n \r\n        # Stop log button\r\n        self.control_log_button = tk.Button(self.main_frame, text=&quot;Pause Log&quot;, command=self.stop_log)\r\n        self.control_log_button.grid(row=0, column=2, sticky=tk.N)\r\n \r\n        # Logs Widget\r\n        self.log_widget = ScrolledText(self.main_frame)\r\n        self.log_widget.grid(row=1, column=0, columnspan=3, sticky=tk.NSEW)\r\n \r\n        # Not editable\r\n        self.log_widget.config(state='disabled')\r\n \r\n        # Queue where the logging handler will write\r\n        self.log_queue = Queue.Queue()\r\n \r\n        # Stup the logger\r\n        l = logging.getLogger('logger')\r\n        l.setLevel(self.log_level)\r\n        formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')\r\n        # Use the QueueLogger as Handler\r\n        hl = QueueLogger(queue=self.log_queue)\r\n        hl.setFormatter(formatter)\r\n        l.addHandler(hl)\r\n        self.logger = logging.getLogger('logger')\r\n \r\n        # Setup the update_widget callback reading logs from the queue\r\n        self.start_log()\r\n        self.run_server()\r\n \r\n    def stop_log(self):\r\n        self.logger.debug(&quot;Pausing the logger&quot;)\r\n        if self.logger_alarm is not None:\r\n            self.log_widget.after_cancel(self.logger_alarm)\r\n            self.control_log_button.configure(text=&quot;Start Log&quot;, command=self.start_log)\r\n            self.logger_alarm = None\r\n \r\n    def start_log(self):\r\n        self.logger.debug(&quot;Starting the logger&quot;)\r\n        self.update_widget(self.log_widget, self.log_queue)\r\n        self.control_log_button.configure(text=&quot;Pause Log&quot;, command=self.stop_log)\r\n \r\n    def update_widget(self, widget, queue):\r\n        widget.config(state='normal')\r\n        # Read from the Queue and add to the log widger\r\n        while not queue.empty():\r\n            line = queue.get()\r\n            widget.insert(tk.END, line)\r\n            widget.see(tk.END)  # Scroll to the bottom\r\n            widget.update_idletasks()\r\n        widget.config(state='disabled')\r\n        self.logger_alarm = widget.after(10, self.update_widget, widget, queue)\r\n \r\n    def clear_log(self):\r\n        self.log_widget.config(state='normal')\r\n        self.log_widget.delete(0.0, tk.END)\r\n        self.log_widget.config(state='disabled')\r\n \r\n    def run_server(self):\r\n        self.logger.debug(&quot;Starting thread&quot;)\r\n        try:\r\n            portvalue=8081\r\n            print 'started httpssserver...'\r\n            url = 'httpss:\/\/localhost:8036\/'\r\n            url = 'httpss:\/\/localhost:'+str(portvalue)+'\/'\r\n            b=str(portvalue)\r\n            #url.__add__(b)\r\n            #url.__add__('\/')\r\n            print url\r\n            self.logger.debug(url)\r\n            self.server = HTTPServer(('', portvalue), MyHandler)\r\n            # Open URL in a new tab, if a browser window is already open.\r\n            #self.server.serve_forever()\r\n\r\n            #self.server = LoggedUDPServer((self.ip, self.port), UDPHandler, self.logger)\r\n            self.server_thread = threading.Thread(name='server', target=self.server.serve_forever)\r\n            self.server_thread.daemon = True\r\n            self.server_thread.start()\r\n            self.control_button.configure(text=&quot;Stop Server&quot;, command=self.stop_server)\r\n            #webbrowser.open_new_tab(url)\r\n        except Exception, e:\r\n            self.logger.error(&quot;Cannot start the server: %s&quot; % e)\r\n            raise e\r\n \r\n    def stop_server(self):\r\n        self.logger.debug(&quot;Stopping server&quot;)\r\n        self.server.shutdown()\r\n        self.server.socket.close()\r\n        self.logger.debug(&quot;Server stopped&quot;)\r\n        self.control_button.configure(text=&quot;Run Server&quot;, command=self.run_server)\r\n \r\nif __name__ == &quot;__main__&quot;:\r\n    root = tk.Tk()\r\n    if len(sys.argv) == 2:\r\n        port = int(sys.argv&#x5B;1])\r\n        address = '127.0.0.1' #sys.argv&#x5B;1]\r\n        app = MainApplication(root, logging.DEBUG, address, port)\r\n        root.title('ICBlock')\r\n        root.mainloop()\r\n    else:\r\n        port = 8080\r\n        address = '127.0.0.1' #sys.argv&#x5B;1]\r\n        app = MainApplication(root, logging.DEBUG, address, port)\r\n        root.title('ICBlock')\r\n        root.mainloop()\r\n        #print &quot;Error: you must specify address and port..&quot;\r\n        #sys.exit(-1)\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p># Copyright 2015 Powen Ko &lt;powenko@gmail.com&gt; # # [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":8689,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[319],"tags":[],"class_list":["post-8688","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ch30-internet"],"_links":{"self":[{"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/8688"}],"collection":[{"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=8688"}],"version-history":[{"count":1,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/8688\/revisions"}],"predecessor-version":[{"id":8690,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/8688\/revisions\/8690"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/media\/8689"}],"wp:attachment":[{"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=8688"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=8688"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=8688"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}