2013-10-24 137 views
6

我正在嘗試使用http.server來測試Python項目中的所有鏈接。如果我在運行腳本之前啓動服務器,然後在關閉終端窗口時服務器停止,我可以讓腳本工作。但我真的很喜歡腳本本身來啓動和停止服務器。如何從Python腳本中殺死SimpleHTTPServer?

我做了一個測試腳本來簡單地啓動服務器,獲取一個頁面並證明服務器正在運行,然後停止服務器。我似乎無法得到服務器的PID。當我嘗試殺死腳本運行後此腳本報告的pid時,我收到一條消息,指出沒有這樣的過程;但服務器仍在運行。

如何爲服務器獲取正確的pid,或者更一般地說,如何從腳本中停止服務器?

import os 
import requests 
from time import sleep 

# Start server, in background. 
print("Starting server...") 
os.system('python -m http.server &') 
# Make sure server has a chance to start before making request. 
sleep(1) 

print "Server pid: " 
os.system('echo $$') 

url = 'http://localhost:8000/index.html' 
print("Testing request: ", url) 
r = requests.get(url) 
print("Status code: ", r.status_code) 
+2

使用你可以使用'subprocess.Popen',而不是'OS .system',它提供了許多額外的功能,包括終止產生的子進程。或者,您可以「導入SimpleHTTPServer」並直接在腳本中使用它... – l4mpi

+0

這很有幫助,但您是否介意多說一點?我似乎發現了有關使用SimpleHTTPServer的唯一參考資料,並討論瞭如何從命令行使用它;我不太清楚如何在python腳本中停止和啓動服務器。我也從來沒有使用過程,所以我不太確定如何啓動服務器子進程,然後停止它。積極搜索... – japhyr

+1

['subprocess' documentation](http://docs.python.org/2/library/subprocess.html)有你需要的所有信息,參見關於'Popen'構造函數和使用'Popen'對象 - 你可以做一些類似於'server = Popen([「python」,「-m」,「SimpleHTTPServer」]),然後使用'server.terminate()'或'server.kill()'來結束這個過程。至於在腳本中啓動一個'SimpleHTTPServer',只需看看SimpleHTTPServer中的'if __name__ =='__main __「:'塊。py - 只需保留對BaseServer實例的引用並關閉它(它是TCPServer子類,所以TCPServer文檔應該有所幫助)。 – l4mpi

回答

6

下面是我在做什麼:

import threading 

try: 
    from http.server import HTTPServer, SimpleHTTPRequestHandler # Python 3 
except ImportError: 
    from SimpleHTTPServer import BaseHTTPServer 
    HTTPServer = BaseHTTPServer.HTTPServer 
    from SimpleHTTPServer import SimpleHTTPRequestHandler # Python 2 

server = HTTPServer(('localhost', 0), SimpleHTTPRequestHandler) 
thread = threading.Thread(target = server.serve_forever) 
thread.daemon = True 
thread.start() 

def fin(): 
    server.shutdown() 

print('server running on port {}'.format(server.server_port)) 

# here is your program 

如果你在程序中調用fin,然後關閉服務器。

+0

我現在正在使用Python 2,但我也很喜歡Python 3上運行的。我收到了一個錯誤'沒有名爲HTTPServer的模塊',所以我將Python 2導入從'BaseHTTPServer導入HTTPServer'。導入工作,但後來我得到一個錯誤,「__init __()有一個意想不到的關鍵字參數'守護進程'」。如果我使用我自己版本的腳本,或者我只是複製腳本並修復導入,我會得到這個結果。有什麼建議麼? – japhyr

+0

我用另外一行修正了deamon參數。這應該在Python 3和2下工作 - 希望。 – User

+0

你能用Ctrl-C殺死服務器嗎? –

1

我得到了這個運行,但我很好奇聽到這是如何比較上面的用戶的答案。在看到接受的答案here後,我想出了這個問題。

import subprocess 
import requests 
import os 
import signal 
from time import sleep 

print "Starting server..." 
cmd = 'python -m SimpleHTTPServer' 
pro = subprocess.Popen(cmd, shell=True, preexec_fn=os.setsid) 

# Make sure server has a chance to start before making request. 
sleep(1) 

url = 'http://localhost:8000/index.html' 
print "Testing request: ", url 
r = requests.get(url) 
print "Status code: ", r.status_code 

os.killpg(pro.pid, signal.SIGTERM) 
3

少許修改上面的用戶代碼:

import threading 
try: 
    from http.server import HTTPServer, BaseHTTPRequestHandler # Python 3 
except ImportError: 
    import SimpleHTTPServer 
    from BaseHTTPServer import HTTPServer # Python 2 
    from SimpleHTTPServer import SimpleHTTPRequestHandler as BaseHTTPRequestHandler 
server = HTTPServer(('localhost', 0), BaseHTTPRequestHandler) 
thread = threading.Thread(target = server.serve_forever) 
thread.deamon = True 
def up(): 
    thread.start() 
    print('starting server on port {}'.format(server.server_port)) 
def down(): 
    server.shutdown() 
    print('stopping server on port {}'.format(server.server_port)) 
+0

爲我工作:D –

0

我用瀏覽器打開的解決方案:

文件:http.py

import SimpleHTTPServer 
import SocketServer 
import threading 
import webbrowser 
import platform 
from socket import SOL_SOCKET,SO_REUSEADDR 

class HTTPServer(): 

    def __init__(self,port=8000,url='http://localhost'): 
     self.port = port 
     self.thread = None 
     self.httpd = None     
     self.run = False 
     self.url = url 

     os = platform.system() 
     if os=='Linux': 
      self.browser_path = "/usr/bin/google-chrome %s"    
     elif os == 'Windows': 
      self.browser_path = "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe %s" 
     else: 
      print("Chrome not found!") 


    def start(self):   
     self.run = True  
     self.httpd = SocketServer.TCPServer(("", self.port), SimpleHTTPServer.SimpleHTTPRequestHandler) 
     self.httpd.socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) 
     self.thread = threading.Thread(target = self._serve) 
     self.thread.start() 
     webbrowser.get(str(self.browser_path)).open(self.url+":"+str(self.port)+"/") 


    def _serve(self):   
     while self.run: 
      self.httpd.handle_request() 

    def stop(self): 
     self.run = False 
     self.httpd.server_close() 

後,只需運行:

from http import HTTPServer 

server = HTTPServer() 
server.start() 

raw_input("Enter to close") 

server.stop() 
+0

而不是打開Chrome,您可以在Windows上使用'start%s'並在OSX上使用'open%s'(不確定Linux)打開默認瀏覽器。 –

0

這是解決問題的解決方案。工程於蟒3.

import os 
import threading 
import webbrowser 
from http.server import HTTPServer, SimpleHTTPRequestHandler 


def simple_http_server(host='localhost', port=4001, path='.'): 

    server = HTTPServer((host, port), SimpleHTTPRequestHandler) 
    thread = threading.Thread(target=server.serve_forever) 
    thread.deamon = True 

    cwd = os.getcwd() 

    def start(): 
     os.chdir(path) 
     thread.start() 
     webbrowser.open_new_tab('http://{}:{}'.format(host, port)) 
     print('starting server on port {}'.format(server.server_port)) 

    def stop(): 
     os.chdir(cwd) 
     server.shutdown() 
     server.socket.close() 
     print('stopping server on port {}'.format(server.server_port)) 

    return start, stop 

simple_http_server將返回startstop功能

>>> start, stop = simple_http_server(port=4005, path='/path/to/folder') 

,你可以作爲

>>> start() 
starting server on port 4005 

127.0.0.1 - - [14/Aug/2016 17:49:31] "GET/HTTP/1.1" 200 - 

>>> stop() 
stopping server on port 4005