关于python http.server 开启多线程并发的问题

发布时间 2023-12-18 11:59:05作者: 学不会xuebuhui

问题描述

thon中的http.server模块是单线程的,这意味着它一次只能处理一个请求,而其他请求必须等待。

为了解决这个问题,您可以考虑使用多线程或异步处理来处理并发请求。您可以使用Python的ThreadingMixIn来创建一个支持多线程的HTTP服务器,或者考虑使用异步框架如asyncio来处理请求。

另外,您还可以考虑使用更高级的Web框架,如Flask、Django或Tornado,它们提供了更多的功能和性能优化,能够更好地处理并发请求。

如果您需要关于如何实现多线程或异步处理的具体代码示例,或者有其他问题需要解决,请随时告诉我,我会尽力帮助您。

# -*- coding: utf-8 -*-
from http.server import HTTPServer, BaseHTTPRequestHandler
import os
import urllib
from http import HTTPStatus
import re
import glob
import xml.etree.ElementTree as ET
from html import escape
#ip, port config
host = ('0.0.0.0', 8890)
base_path=os.getcwd().replace("\\",'/')
print(f"根目录{base_path}")
class Resquest(BaseHTTPRequestHandler):
    def do_GET(self):
        # print(self.path)
        if self.path == '/':
            self.send_response(200)
            self.end_headers()
            f = open("index.html", 'r',encoding='UTF-8')
            #读html然后用正则替换
            content = f.read()
            ##
            newest_sfc,newest_advance_sfc=self.report_latest()
            content=re.sub(r"sfc_report",newest_sfc,content)
            content=re.sub(r"advance_sfcreport",newest_advance_sfc,content)
            self.wfile.write(content.encode())
        else:
            if self.path.endswith('.svg'):
                try:
                    with open(self.path[1:], 'rb') as f:
                        self.send_response(200)
                        self.send_header('Content-type', 'image/svg+xml')
                        self.end_headers()
                        self.wfile.write(f.read())
                except FileNotFoundError:
                    self.send_response(404)
                    self.end_headers()
                    self.wfile.write(b'File not found')
            elif self.path.endswith('.html'):
                try:
                    with open(self.path[1:], 'rb') as f:
                        self.send_response(200)
                        self.send_header('Content-type', 'text/html')
                        self.end_headers()
                        self.wfile.write(f.read())
                except FileNotFoundError:
                    self.send_response(404)
                    self.end_headers()
                    self.wfile.write(b'File not found')
            # 把所有得siderbar 定位到根目录
            # elif self.path.endswith('_siderbar.md'):
            #     pass
            else:
                current=base_path+ self.path
                print(f"base_path:{base_path}当前路径{current}")
                if os.path.isdir(current):
                    print("文件夹")
                    self.send_response(200)
                    self.end_headers()

                    content ="<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"><title>Directory listing</title></head>"+'</body>'+self.get_directory("."+self.path) + '</body>'+"</html>"
                    # 里面需要传入二进制数据,用encode()函数转换为二进制数据
                    #写到wfile这个对象才能变成网页展示
                    self.wfile.write(content.encode())
                    # self.get_directory("."+self.path)
                else:
                    try:
                        path = urllib.parse.unquote(self.path[1:])
                        f = open(path, 'rb')
                        self.send_response(200)
                        self.end_headers()
                        self.wfile.write(f.read())
                    except FileNotFoundError:
                        self.send_response(404)
                        self.end_headers()
                        self.wfile.write(b'<h1>File Not Found</h1>')


    def parse_query(self):
        self.queryString = urllib.parse.unquote(self.path.split('?', 1)[1])
        self.queries = urllib.parse.parse_qs(self.queryString)
        print(self.queries)
    def report_latest(self):
        # 获取当前文件夹下的所有文件
        # files=glob.glob("*")
        files = os.listdir("./report")
        print("listfile",files)
        # 获取文件的修改时间
        # sfc报告
        file_times = [(f, os.path.getmtime(os.path.join("report/",f))) for f in files if f.startswith("sfc")]
        # 根据修改时间排序文件
        file_times.sort(key=lambda x: x[1])
        # 获取最新的文件
        newest_sfc = file_times[-1][0]
        # advance_sfc报告
        file_times = [(f, os.path.getmtime(os.path.join("report/",f))) for f in files if f.startswith("advan")]
        # 根据修改时间排序文件
        file_times.sort(key=lambda x: x[1])
        # 获取最新的文件
        newest_advance_sfc = file_times[-1][0]
        print("The newest file in the current directory is:", newest_sfc,newest_advance_sfc)
        return (newest_sfc,newest_advance_sfc)

    def get_directory(self, path) -> str:
        if path==".":
            path="/"
        try:
            list = os.listdir(path)
        except OSError:
            self.send_error(
                HTTPStatus.NOT_FOUND,
                "No permission to list directory")
            return None
        list.sort(key=lambda a: a.lower())
        r = []
        displaypath = os.path.abspath(path)
        title = 'Directory listing for %s' % displaypath
        r.append('<h1>%s</h1>' % title)

        for name in list:
            fullname = os.path.join(path, name).replace("\\",'/')
            print("完整路径:",fullname)
            displayname = linkname = name
            # Append / for directories or @ for symbolic links
            if os.path.isdir(fullname):

                displayname = name +"/"
                linkname = fullname +"/"
                print("文件夹",linkname)
            if os.path.isfile(fullname):
                linkname = fullname

                displayname = name
                print("单文件",linkname)
                # Note: a link to a directory displays with @ and links with /
            r.append('<li><a href="%s">%s</a></li>' % (linkname, displayname))
        # print(''.join(r))
        return ''.join(r)


if __name__ == '__main__':


    server = HTTPServer(host, Resquest)
    print("Starting server, listen at: %s:%s" % host)
    server.serve_forever()

python httpsever 如何实现多并发

要在Python中实现多并发的HTTP服务器,您可以使用http.server模块的ThreadingHTTPServersocketserver.ThreadingMixIn。这将允许服务器在多个线程中处理并发请求。

下面是一个简单的示例代码,演示了如何使用ThreadingHTTPServer创建一个多线程的HTTP服务器:

from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler

class MyHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write(b"Hello, world")

if __name__ == '__main__':
    server_address = ('', 8000)
    httpd = ThreadingHTTPServer(server_address, MyHandler)
    print('Starting server, listen at: %s:%s' % server_address)
    httpd.serve_forever()

在这个示例中,我们使用ThreadingHTTPServer创建了一个多线程的HTTP服务器,并指定了处理请求的处理程序MyHandler。这样,服务器就能够在多个线程中处理并发请求了。

请注意,尽管多线程可以提高服务器的并发处理能力,但也需要注意线程安全性和资源竞争的问题。确保您的处理程序是线程安全的,并且适当地处理共享资源和状态。

希望这可以帮助您实现多并发的HTTP服务器。如果您有其他问题或需要进一步的帮助,请随时告诉我。