用 python 寫一個簡單的 http server,遇到問題

708 views
Skip to first unread message

betaparticle

unread,
Jan 10, 2012, 9:19:25 AM1/10/12
to python.tw
大家好,我最近遇到一個困擾的事,想問大家的意見

我用 python 的 BaseHTTPServer 做了一個 http server,叫 server.py
在畫面上,有兩個按鈕,一個是 run,一個是 exit
當我按 run 這個按鈕時,server 會用 subprocess 執行一個要執行很久的程式 longprocess.py。
在 run 的同時,我可能需要會把 server 停掉做更新,而去按下 exit 按鈕。
當按下 exit 按鈕後,server 會停掉,而剛按下 run 的 process 會持續執行。
我希望再執行 server.py,就能夠再處理瀏覽器來的 request。
但是當我再執行 server.py,卻不能再收到瀏覽器來的 request。
除非我把 longprocess.py 停掉之後,瀏覽器再送 request,剛啟動的 server.py 才會收到。

我以為是 myHTTPServer 裡面的 socket 沒 release
所以特別有執行 self.server_close() 也試過 self.socket.close()
也試著用 self.allow_reuse_address = True
都沒有用。

後面是我的程式碼。我的環境是 windows 7
按以下的步驟就可以重現我的情況

(1)執行 server.py 之後,用瀏覽器前往 http://127.0.0.1:9001
(2)按 run 按鈕,longprocess.py 會執行 60 秒
(3)按 exit 按鈕,server.py 會關掉
(4)再執行 server.py
(5)用瀏覽器前往 http://127.0.0.1:9001,會發現網頁沒回應
(6)等 longprocess.py,再用瀏覽器前往 http://127.0.0.1:9001,網頁有回應。


# -*- coding: utf8 -*-

import BaseHTTPServer
import threading
import subprocess
import cgi

class myHTTPServer(BaseHTTPServer.HTTPServer):
def __init__(self, *args, **kw):
BaseHTTPServer.HTTPServer.__init__(self, *args, **kw)
self.running = 1
def serve_forever(self):
while self.running:
self.handle_request()
self.server_close()
print 'myHTTPServer: serve_forever(): end'
def stop(self):
self.running = 0

def execute_nowait_command(cmd):
p =
subprocess.Popen(cmd.encode('cp950') ,creationflags=subprocess.CREATE_NEW_CONSOLE)

class myHandler(BaseHTTPServer.BaseHTTPRequestHandler):
server_version= "MyHandler/1.1"
current_request_path = "/"

def redirect(self,path):
self.send_response(301)
self.send_header("Location", '/')
self.end_headers()

def do_GET(self):
self.log_message( "Command: %s Path: %s Headers: %r"
% ( self.command, self.path,
self.headers.items() ) )
if self.path == '/':
self.dumpReq( None )
else:
self.redirect('/')

def do_POST( self ):
form= cgi.FieldStorage(
fp=self.rfile,
headers=self.headers,
environ={'REQUEST_METHOD':'POST',
'CONTENT_TYPE':self.headers['Content-Type'],
})
self.log_message( "Command: %s Path: %s Headers: %r"
% ( self.command, self.path,
self.headers.items() ) )
self.log_message("field start")
for field in form.keys():
self.log_message("field %s : %s" % (field,
form[field].value))

if self.path == '/run':
execute_nowait_command('python.exe longprocess.py')
self.log_message("field end")
self.dumpReq( None )
for field in form.keys():
self.log_message("field %s : %s" % (field,
form[field].value))
if field=="cmd" and form[field].value=="exit":
httpd.stop()
print 'myHandler: do_POST(): end'


def dumpReq( self, formInput=None ):
response= "<html><head><meta http-equiv='Content-type'
content='text/html; charset=utf8' /></head>"
response+= '<body>'
response+= "<form action='/' method='POST'>"
response+= "<input type=submit name=cmd value=exit></input>"
response+= "</form>"
response+= "<form action='/run' method='POST'>"
response+= "<input type=submit name=cmd value=run></input>"
response+= "</form>"
response+= "</body></html>"
self.sendPage( "text/html; charset=utf-8",
response.encode('utf8') )

def sendPage( self, type, body ):
self.send_response( 200 )
self.send_header( "Content-type", type )
self.send_header( "Content-length", str(len(body)) )
self.send_header( "Location", '/' )
self.end_headers()
self.wfile.write( body )

class server_in_Thread(threading.Thread):
def __init__(self):
threading.Thread.__init__ ( self )
def run(self):
global httpd
httpd.serve_forever()

def server_start():
PORT = 9001

Handler = myHandler

global httpd
httpd = myHTTPServer(("", PORT), Handler)
print "server_start() serving at port", PORT

global tt
tt=server_in_Thread()
tt.start()
return httpd

def wait_server_stop():
print 'wait_server_stop(): start'
global tt
tt.join()
print 'wait_server_stop(): stop'

if __name__ == '__main__':
tt = None
httpd = None

server_start()
wait_server_stop()
print "__main__: go end"

betaparticle

unread,
Jan 10, 2012, 9:22:30 AM1/10/12
to python.tw
我忘了附 longprocess.py 的內容
它的內容如下:

import time
print __file__,'start'
time.sleep(60)

On Jan 10, 10:19 pm, betaparticle <ricky.t...@gmail.com> wrote:
> 大家好,我最近遇到一個困擾的事,想問大家的意見
>
> 我用 python 的 BaseHTTPServer 做了一個 http server,叫 server.py
> 在畫面上,有兩個按鈕,一個是 run,一個是 exit
> 當我按 run 這個按鈕時,server 會用 subprocess 執行一個要執行很久的程式 longprocess.py。
> 在 run 的同時,我可能需要會把 server 停掉做更新,而去按下 exit 按鈕。
> 當按下 exit 按鈕後,server 會停掉,而剛按下 run 的 process 會持續執行。
> 我希望再執行 server.py,就能夠再處理瀏覽器來的 request。
> 但是當我再執行 server.py,卻不能再收到瀏覽器來的 request。
> 除非我把 longprocess.py 停掉之後,瀏覽器再送 request,剛啟動的 server.py 才會收到。
>
> 我以為是 myHTTPServer 裡面的 socket 沒 release
> 所以特別有執行 self.server_close() 也試過 self.socket.close()
> 也試著用 self.allow_reuse_address = True
> 都沒有用。
>
> 後面是我的程式碼。我的環境是 windows 7
> 按以下的步驟就可以重現我的情況
>
> (1)執行 server.py 之後,用瀏覽器前往http://127.0.0.1:9001
> (2)按 run 按鈕,longprocess.py 會執行 60 秒
> (3)按 exit 按鈕,server.py 會關掉
> (4)再執行 server.py
> (5)用瀏覽器前往http://127.0.0.1:9001,會發現網頁沒回應
> (6)等 longprocess.py,再用瀏覽器前往http://127.0.0.1:9001,網頁有回應。
Reply all
Reply to author
Forward
0 new messages