关于python http.server 开启多线程并发的问题
问题描述
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
模块的ThreadingHTTPServer
或socketserver.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服务器。如果您有其他问题或需要进一步的帮助,请随时告诉我。
再低版本python3可能http.server模块中并没有ThreadingHTTPServer
这个类。实现多并发的HTTP服务器需要使用socketserver
模块中的ThreadingMixIn
。
下面是一个修正后的示例代码,演示了如何使用ThreadingMixIn
创建一个多线程的HTTP服务器:
from http.server import HTTPServer, BaseHTTPRequestHandler
from socketserver import ThreadingMixIn
import threading
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")
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
pass
if __name__ == '__main__':
server_address = ('', 8000)
httpd = ThreadedHTTPServer(server_address, MyHandler)
print('Starting server, listen at: %s:%s' % server_address)
httpd.serve_forever()
在这个示例中,我们创建了一个名为ThreadedHTTPServer
的类,它继承自ThreadingMixIn
和HTTPServer
。这样,我们就能够使用多线程处理并发请求了。
希望这次能够解决您的问题。如果您有其他问题或需要进一步的帮助,请随时告诉我。