2013-10-24 7 views
6

Ich versuche http.server zu verwenden, um alle Links in einem Python-Projekt zu testen. Ich kann mein Skript zum Laufen bringen, wenn ich den Server vor dem Ausführen meines Skripts starte, und dann stoppt der Server, wenn ich das Terminalfenster schließe. Aber ich möchte wirklich, dass das Skript selbst den Server startet und stoppt.Wie kann ich SimpleHTTPServer in einem Python-Skript beenden?

Ich machte ein Testskript, um einfach den Server zu starten, eine Seite zu erhalten und zu beweisen, dass der Server läuft, und dann den Server zu stoppen. Ich kann nicht die PID des Servers bekommen. Wenn ich versuche, die PID zu beenden, die dieses Skript meldet, nachdem das Skript ausgeführt wurde, erhalte ich die Meldung, dass es keinen solchen Prozess gibt. aber der Server läuft noch.

Wie bekomme ich die richtige PID für den Server, oder allgemeiner wie stoppe ich den Server aus dem Skript?

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

könnten Sie 'subprocess.Popen' statt' os zurück .system', bietet es eine Menge zusätzlicher Funktionalität einschließlich der Beendigung des erzeugten Subprozesses. Oder Sie können einfach SimpleHTTPServer importieren und direkt in Ihrem Skript verwenden ... – l4mpi

+0

Das ist hilfreich, aber macht es Ihnen etwas aus, ein bisschen mehr zu sagen? Die einzigen Referenzen, die ich bei der Verwendung von SimpleHTTPServer finde, sprechen davon, sie über die Befehlszeile zu verwenden. Ich bin mir nicht sicher, wie ich den Server innerhalb eines Python-Skripts stoppen und starten kann. Ich habe auch noch nie zuvor Prozesse verwendet, daher bin ich mir nicht sicher, wie ich den Server-Subprozess starten soll, und stoppe ihn dann. Aktiv googeln ... – japhyr

+1

Die [subprocess' Dokumentation] (http://docs.python.org/2/library/subprocess.html) hat alle Informationen, die Sie benötigen, siehe die Abschnitte über den 'Popen' Konstruktor und die Verwendung 'Popen' Objekte - Sie könnten etwas wie' server = Popen (["python", "-m", "SimpleHTTPServer"]) '' machen und dann 'server.terminate()' oder 'server.kill()' verwenden um beende den Prozess. Um einen 'SimpleHTTPServer' in einem Skript zu starten, sehen Sie sich einfach den 'if __name__ ==" __main __ ":' -Block in SimpleHTTPServer an.py - behalte einfach einen Verweis auf die BaseServer-Instanz und schließe sie (es ist eine TCPServer-Unterklasse, also sollten die TCPServer-Dokumente helfen). – l4mpi

Antwort

6

Hier ist, was ich tue:

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 

Wenn Sie fin in Ihrem Programm aufrufen, dann schaltet sich der Server herunter.

+0

Ich benutze Python 2 im Moment, aber ich würde es auch gerne auf Python 3 laufen lassen. Ich habe den Fehler 'kein Modul namens HTTPServer' erhalten, also habe ich den Import von Python 2 in 'von BaseHTTPServer import HTTPServer' geändert. Der Import hat funktioniert, aber dann habe ich einen Fehler bekommen, dass "__init __() ein unerwartetes Schlüsselwort-Argument 'daemon'" bekommen hat. Ich bekomme das, wenn ich meine eigene Version dieses Skripts verwende, oder wenn ich nur dein Skript kopiere und den Import repariere. Irgendwelche Vorschläge? – japhyr

+0

Ich habe das Deamon-Argument mit einer zusätzlichen Zeile behoben. Dies sollte jetzt unter Python 3 und 2 funktionieren - hoffentlich. – User

+0

Können Sie den Server mit Strg-C beenden? –

1

Ich habe das zu laufen, aber ich bin neugierig zu hören, wie dies mit der obigen Antwort von User vergleicht. Ich kam auf diese Antwort, nachdem ich die akzeptierte Antwort here angesehen hatte.

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

Eine leichte Modifikation von Code über den Benutzer:

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

Arbeitete für mich: D –

0

Meine Lösung mit Browser-Öffnung:

Datei: 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() 

Nach nur laufen :

from http import HTTPServer 

server = HTTPServer() 
server.start() 

raw_input("Enter to close") 

server.stop() 
+0

Anstatt Chrome zu öffnen, können Sie 'start% s' auf Windows und'% s' auf OSX öffnen (nicht sicher für Linux), um den Standardbrowser zu öffnen. –

0

Dies ist eine Verschlusslösung für das Problem. Funktioniert auf Python 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 die

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

, die Sie verwenden können, als

>>> 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 
Verwandte Themen