python 노트 (4) 간단 한 웹 서버

5466 단어
앞의 노트 에 장식 기와 정규 표현 식 이 언급 되 어 있 습 니 다. 여기 서 간단 한 웹 서버 를 실현 하 겠 습 니 다.구체 적 으로 기능 에 있어 서 먼저 브 라 우 저 를 통 해 방문 할 수 있 고 또 하 나 는 간단 한 모델 시스템 이 있다 는 것 이다.
1. 네트워크 부분
네트워크 부분 에 사용 되 는 tisted, 이 코드 는 tisted 책 에서 복사 되 었 습 니 다.복잡 하 다 고 생각 하지 말고 그대로 베껴 라. 나 도 트위스트 를 모른다.여기 서 말 하고 자 하 는 것 은 HTTP 프로 토 콜 의 줄 당 데이터 가 \r
로 끝 나 므 로 이 프로 토 콜 은 basic.LineReceiver 에서 계승 된다 는 것 이다.
from twisted.protocols import basic
from twisted.internet import protocol, reactor
from template import render_template
class HTTPProtocol(basic.LineReceiver):
    def __init__(self,factory):
        self.lines = []
        self.factory = factory

    def lineReceived(self, line):
        self.lines.append(line)
        if not line:
            # self.sendResponse(self.factory.app.dispatch(lines))
            self.sendResponse(self.factory.app.dispatch(self.lines))
    def sendResponse(self,data):
        self.sendLine(b"HTTP/1.1 200 OK")
        self.sendLine(b"")
        # responseBody = "You said:\r
\r
" + "\r
".join(self.lines) responseBody = data.encode('utf-8')+b'\r
' self.transport.write(responseBody) self.transport.loseConnection() class HTTPFactory(protocol.ServerFactory): def __init__(self,app): self.app = app def buildProtocol(self, addr): return HTTPProtocol(self)

2 경로 장식 기
앞에서 나 는 장식 기의 문 제 를 언급 한 적 이 있 는데, 모든 경로 에 대응 하 는 함수 도 장식 기 를 사용 하여 실현 할 수 있다.경 로 를 경로 장식 기의 함수 와 연결 시 키 고 이 데이터 구 조 를 간단하게 사용 합 니 다 dict.실 현 된 코드 는 아래 에 열거 되 어 있 습 니 다. route 함 수 는 구성원 함수 이 고 가장 중요 한 줄 코드 는 self.routes[url] = func 입 니 다.원래 장식 기 는 이 코드 만 있 으 면 작 동 할 수 있 지만 장식 기 가 함수 하 나 를 되 돌려 주지 않 으 면 wrapper 이 함 수 를 말 합 니 다. 그러면 한 함수 에 여러 개의 경로 장식 기 를 사용 할 수 없습니다.
class Dongge():
    def __init__(self):
        self.routes = {}

    def dispatch(self,lines):
        line = lines[0].decode('utf-8')
        method,url,version = line.split(' ')
        print(line)
        print(self.routes)
        if url in self.routes:
            return self.routes[url]()
        return 'No such url resource'

    def route(self,url):
        def df(func):
            self.routes[url] = func
            def wrapper(*args, **kwargs):
                return func(*args,**kwargs)
            return wrapper
        return df

app = Dongge()

@app.route('/')
@app.route('/index')
def index():
    return 'index'

3 템 플 릿
모델 은 앞에서 이미 이 방면 의 내용 을 언급 한 적 이 있 는데, 여 기 는 render_template 을 포장 하면 바로 사용 할 수 있다.
def view(self,tname,context):
        path = '{}/{}.html'.format(self.templatedir,tname)
        try:
            with open(path,'r') as f:
                html = f.read()
                print(html)
                return render_template(html,context)
        except Exception as e:
            print(e)
            return ''

4 보충
코드 를 실행 시 키 는 것 은 간단 한 두 마디 코드 입 니 다.
reactor.listenTCP(8000, HTTPFactory(app))
reactor.run()

만약 당신 이 이 코드 를 뛰 어 다 니 면 무슨 문제 가 있 을 것 입 니까? 물론 코드 가 모두 실행 되 었 으 니 큰 문제 가 없 을 것 입 니 다.하지만 코드 를 수정 할 때마다 서버 를 다시 실행 해 야 한 다 는 고민 도 있다.내 코드 의 변경 을 감시 하고 서버 를 자동 으로 다시 시작 할 수 있 는 것 이 필요 하 다 는 것 일지 도 모른다.이 문 제 는 매우 간단 하 다. 코드 를 보면 이 코드 는 모두 인터넷 에서 복사 한 것 으로 약간 수정 되 었 다.
#start.py
# -*- coding:utf-8 -*-
from watchdog.observers import Observer
from watchdog.events import *
import time
from server import start
from multiprocessing import Process
class FileEventHandler(FileSystemEventHandler):
    def __init__(self):
        FileSystemEventHandler.__init__(self)

    def on_moved(self, event):
        if event.is_directory:
            print("directory moved from {0} to {1}".format(event.src_path,event.dest_path))
        else:
            print("file moved from {0} to {1}".format(event.src_path,event.dest_path))

    def on_created(self, event):
        if event.is_directory:
            print("directory created:{0}".format(event.src_path))
        else:
            print("file created:{0}".format(event.src_path))

    def on_deleted(self, event):
        if event.is_directory:
            print("directory deleted:{0}".format(event.src_path))
        else:
            print("file deleted:{0}".format(event.src_path))

    def on_modified(self, event):
        if event.is_directory:
            print("directory modified:{0}".format(event.src_path))
        else:
            print("file modified:{0}".format(event.src_path))
            #         start.py         
            if event.src_path.find('start.py') == -1:
                self.startserver()
    '''
                ,            
    '''
    def startserver(self):
        if hasattr(self,'p'):
            self.p.terminate()
            del self.p
        p = Process(target=start)
        p.start()
        self.p = p

if __name__ == "__main__":
    observer = Observer()
    event_handler = FileEventHandler()
    event_handler.startserver()
    observer.schedule(event_handler,"./",True)
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

좋은 웹페이지 즐겨찾기