2013-10-24 18 views
6

Tôi đang cố gắng sử dụng http.server để kiểm tra tất cả các liên kết trong một dự án Python. Tôi có thể nhận được kịch bản của tôi để làm việc nếu tôi khởi động máy chủ trước khi chạy kịch bản của tôi, và sau đó máy chủ dừng lại khi tôi đóng cửa sổ đầu cuối. Nhưng tôi thực sự thích bản thân kịch bản để bắt đầu và dừng máy chủ.Làm thế nào để giết SimpleHTTPServer từ bên trong một tập lệnh Python?

Tôi đã thực hiện một tập lệnh thử nghiệm để chỉ cần khởi động máy chủ, nhận một trang và chứng minh máy chủ đang chạy, sau đó dừng máy chủ. Tôi dường như không nhận được pid của máy chủ. Khi tôi cố gắng để diệt các pid rằng kịch bản này báo cáo sau khi kịch bản chạy, tôi nhận được một thông báo rằng không có quá trình như vậy; nhưng máy chủ vẫn đang chạy.

Làm cách nào để nhận đúng pid cho máy chủ hoặc nói chung là làm cách nào để dừng máy chủ khỏi tập lệnh?

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

Bạn có thể sử dụng 'subprocess.Popen' thay vì' os .system', nó cung cấp rất nhiều chức năng bổ sung bao gồm cả việc chấm dứt tiến trình con sinh ra. Hoặc bạn chỉ có thể 'nhập SimpleHTTPServer' và sử dụng nó trực tiếp trong kịch bản của bạn ... – l4mpi

+0

Điều đó rất hữu ích, nhưng bạn có phiền hơn một chút không? Các tài liệu tham khảo duy nhất tôi dường như tìm về việc sử dụng SimpleHTTPServer nói về việc sử dụng nó từ dòng lệnh; Tôi không chắc chắn làm thế nào để dừng lại và bắt đầu máy chủ từ bên trong một kịch bản python. Tôi cũng chưa bao giờ sử dụng các quy trình trước đây, vì vậy tôi không hoàn toàn chắc chắn cách khởi động tiến trình con của máy chủ, và sau đó dừng nó lại. Chủ động googling ... – japhyr

+1

Tài liệu ['subprocess'] (http://docs.python.org/2/library/subprocess.html) có tất cả thông tin bạn cần, xem các phần về hàm tạo' Popen' và sử dụng Đối tượng 'Popen' - bạn có thể làm một cái gì đó như' server = Popen (["python", "-m", "SimpleHTTPServer"]) 'và sau đó sử dụng' server.terminate() 'hoặc' server.kill() 'để kết thúc quá trình. Để bắt đầu một 'SimpleHTTPServer' trong một kịch bản, chỉ cần nhìn vào' if __name__ == "__main __": 'block trong SimpleHTTPServer.py - chỉ giữ một tham chiếu đến cá thể BaseServer và đóng nó (nó là một lớp con TCPServer, vì vậy các tài liệu TCPServer sẽ giúp). – l4mpi

Trả lời

6

Đây là những gì tôi đang làm:

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 

Nếu bạn gọi fin trong chương trình của bạn, sau đó máy chủ tắt.

+0

Tôi đang sử dụng Python 2 vào lúc này, nhưng tôi cũng thích điều này để chạy trên Python 3. Tôi gặp lỗi 'không có mô-đun tên HTTPServer', vì vậy tôi đã thay đổi việc nhập khẩu Python 2 thành 'từ BaseHTTPServer nhập HTTPServer'. Quá trình nhập đã hoạt động, nhưng sau đó tôi gặp lỗi "__init __() đã nhận được đối số từ khóa không mong muốn 'daemon'". Tôi nhận được điều này nếu tôi sử dụng phiên bản riêng của tập lệnh này hoặc nếu tôi chỉ sao chép tập lệnh của bạn và khắc phục việc nhập. Bất kỳ đề xuất? – japhyr

+0

Tôi đã sửa đối số deamon bằng một dòng bổ sung. Điều này sẽ làm việc theo Python 3 và 2 bây giờ - hy vọng. – User

+0

Bạn có thể giết máy chủ bằng Ctrl-C không? –

1

Tôi đã thực hiện điều này, nhưng tôi tò mò muốn biết điều này so với câu trả lời của Người dùng ở trên như thế nào. Tôi nghĩ ra điều này sau khi nhìn vào câu trả lời được chấp nhận 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

Một sửa đổi chút ít để mã của người sử dụng trên:

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

Làm việc cho tôi: D –

0

Giải pháp của tôi với mở trình duyệt:

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

Sau đó, chỉ cần chạy :

from http import HTTPServer 

server = HTTPServer() 
server.start() 

raw_input("Enter to close") 

server.stop() 
+0

Thay vì mở Chrome, bạn có thể sử dụng 'start% s' trên Windows và' open% s' trên OSX (không chắc chắn Linux) để mở trình duyệt mặc định. –

0

Đây là giải pháp đóng cửa cho sự cố. Hoạt động trên 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 đó sẽ trở lại startstop chức năng

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

mà bạn có thể sử dụng như là

>>> 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 
Các vấn đề liên quan