python制作动态网站_精析Python3实现动态web服务(附服务端源码)

news/2024/5/8 14:12:36/文章来源:https://blog.csdn.net/weixin_39792519/article/details/109941168

实现一个简单的静态web网站,只需将写好的html页面上传到特定的web服务器软件即可,但静态网页其实和图片没什么区别,每次更新网站内容,都需要重新制作html页面,然后上传给提供web服务的软件,替换原来的html页面,也就完成了更新,以一个正常人的思维方式,每次更新内容都要重新生成html的工作实在太蛋疼了!那么能不能让程序自己生成html呢?当然可以,程序就是为将人类从重复繁杂的工作中解放出来而生的!

如果我们提供一个动态网站服务,至少应考虑以下四点:

1.要有稳定的web服务程序(可以使用知名的apache,nginx,这里为了探究原理,我们自己用多进程写一个简单的web服务);

2.要有可用的web网页模板(网络上web模版的数量堪比ppt模板,当然我们可以自己画一张, 10分钟后...算了-_-///,作为后端人员,我们这里用朴素的信息显示就好)

3.要有可填充html模板的内容(内容一般从自己的数据库里取,篇幅所限,我们这里用time.ctime()函数,模拟数据库动态数据);

4.要有处理填写内容的逻辑(这个就是我们要今天主要研究的按照wsgi标准实现的简单的web框架);

一个优秀的动态web框架应该是这样的:

1.web框架要和 web服务器软件 分离开;如果把大量的逻辑处理语句,和html放到一个文件中,后期会难以维护(这也是现在多人开发推崇MVC的原因);

2.一个优秀的web框架要和web服务器软件 有良好的交互通信;这时就需要一个数据交互的标准WSGI(python为自身web框架制定了WSGI标准);

3.一个优秀的web框架要实现,和数据库有良好的读写通信方法;

关于WSGI标准

为了方便表述,先举一个栗子:import timedef app(environ, start_response):

status = '200 OK'

response_headers = [('Content-Type', 'text/plain')]

start_response(status, response_headers)    return str(environ) + '==Hello world from a simple WSGI application!--->%s\n' % time.ctime()

WIGS模型的要点:

1.在web框架模块,以上面的栗子为例,web服务器软件会向web框架传递一个列表(environ)和一个函数(函数体在web服务器软件中实现)的引用(start_response),然后web框架要实现一个app函数,并将 "一个列表"和"一个函数的引用",作为两个参数;

2.传递过来的列表内部存储了N个元组,这些元组包含了web服务器接收到的客户端浏览器的请求信息, 传递过来的函数参数的引用,可以用来返回请求资源的状态反馈(如果请求的资源可以访问,就会返回200,如果资源无法访问,就返回404或502之类的错误;

3.传递过来的函数引用的调用比return更靠前,这样可以在返回正式的网页之前的这段时间,让web服务器软件做好接收数据的准备;(其实可以将函数的引用作为web框架与web服务器软件传递数据的的一种快捷方式);

扩展:其实双重返回的设计思路很常见,比如在tcp四次挥手的过程中,第二次和第三次挥手都是服务器发送数据,客户端接收数据;

第二次服务端向客户端说("客户端,我收到你主动关闭本次连接的消息了!"),第三次服务端向客户端说("客户端,我已经关闭了这次的发送连接,不会给你发数据了,收到了记得回我个消息哈!");

也许有人会认为,既然第二次和第三次都是服务端向客户端发送数据,那应该可以将两条消息一起发送,但实际上,服务器关闭发送数据的通道是需要一定的时间的,如果第二次和第三次一起发送,客户端浏览器就不能在发送第一次消息后,及时确认消息是否送达,而在tcp连接中,及时"确认送达"是一件非常重要的事情!

在web服务器软件模块,至少要实现三个功能:

1.创建 包含客户端请求头消息的列表(作为第一个参数传递);

2.创建一个可以解析返回状态信息的函数(作为第二个参数传递);

3.接收web框架内app函数返回的body,并将body与作为第二个参数的引用的函数的返回状态值组合,一同发送给客户端浏览器;实现源码

1.作者自己编写小型web服务器(以上篇 gevent实现静态web服务器为基础改写)web_server.pyimport socketfrom sys import argvimport geventfrom gevent import monkeyimport timeimport randomimport re# 服务器类class WISG(object):

def __init__(self, port, app):

self.port = port

self.root_dir = "./HTML"

# 创建主套接字

self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        # 允许端口重用

self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)        # 主套接字绑定端口

self.server_socket.bind(("", self.port))        # 主套接字转为被动模式

self.server_socket.listen(128)        # 获取web框架中的函数引用

self.app = app        pass

# 启动服务器对象的入口函数

def run_forever(self):

self.create_new_socket()        pass

# 创建新的套接字,使用gevent,使新的套接字以消耗少量资源的协程方式运行

def create_new_socket(self):

while True:

new_client_socket, new_client_socket_addr = self.server_socket.accept()

gevent.spawn(self.deal_accept_data, new_client_socket)    # 处理接收到的数据

def deal_accept_data(self, new_client_socket):

recv_data = new_client_socket.recv(1024)        # 接收到的请求为utf-8格式,解析数据

recv_data = recv_data.decode("utf-8")        # 如果收到客户端发送的空字符,则关闭连接

if not recv_data:            return

# 将接收到的数据转换为列表

recv_data_list = recv_data.splitlines()        # 获取请求头信息

the_request_header = recv_data_list[0]

file_name = self.get_file_name(the_request_header)

if file_name.endswith(".html"):

print("请求的文件名为%s"%(file_name))

# 向客户端发送文件

self.send_html(file_name, new_client_socket)

new_client_socket.close()        else:

print("进入动态选择模块...")

print("请求的文件名为%s"%(file_name))            # 得到web框架返回的数据

# 创建一个字典

environ = dict()

environ["PATH_INFO"] = file_name            #获得内容

dynamic_content = self.app(environ, self.set_response_header)

new_client_socket.send(self.dynamic_response_headers_info + dynamic_content.encode("utf-8"))

new_client_socket.close()    # 根据请求头信息,获得本地对应以.html或.py尾缀的文件名

def get_file_name(self, the_request_header):

"""GET /index.html HTTP/1.1"""

file_name = re.match(r"[^/]+([^ ]+).*", the_request_header).group(1)        if file_name == "/":

file_name = "/index.html"

return file_name        pass

# 发送静态文件的html到客户端

def send_html(self, file_name, new_client_socket):

try:

f = open(self.root_dir+file_name, "rb")        except Exception as res:

print(res)

print("无法找到网页404")        else:

content = f.read()

respond_body = content

respond_header = "HTTP/1.1 200 OK \r\n"

respond_header += "Content-Type: text/html; charset=utf-8\r\n"

respond_header = respond_header + "\r\n"

# 发送回应

new_client_socket.send(respond_header.encode("utf-8"))

new_client_socket.send(respond_body)

print("内容发送成功!")        pass

def set_response_header(self, status, headers):

#将从web框架收到的状态码,和返回的头信息存储到一个列表里面

self.dynamic_respond_header = [status, headers]        # 组建返回头信息

dynamic_respond_header = "HTTP/1.1 %s \r\n"

dynamic_respond_header += "%s:%s\r\n"%(headers[0][0], headers[0][1])

dynamic_respond_header += "\r\n"

# 将列表中的数据进行整理,转为可直接使用的"返回头"信息,然后存到类变量dynamic_response_headers_info

self.dynamic_response_headers_info =  dynamic_respond_header.encode("utf-8")        passdef main():

monkey.patch_all()    # 创建web服务器

if len(argv) == 3:

port = int(argv[1])        # web框架名称

frame_name = re.match(r"([^:]+):(.+)", argv[2]).group(1)        # web框架中主调函数的名称

app_name = re.match(r"([^:]+):(.+)", argv[2]).group(2)        # 动态导入框架函数app

web_frame_module = __import__(frame_name)        # 获得框架中的主调函数

app = getattr(web_frame_module, app_name)    # 传入端口号,和来自web框架的函数app

web_server = WISG(port, app)

print("app的名字为%s,框架的名字为%s,端口号为%s"%(frame_name, app_name, port))

print("请在地址栏访问 127.0.0.1:%d"%(port))    # 启动web服务器

web_server.run_forever()    passif __name__ == "__main__":

main()

2.按照wsgi标准实现的web框架web_frame.pyimport timeimport reimport codecs

template_root = "./HTML"file_name = Nonedef read_file(file_name):

try:

file_name = template_root+file_name

f = codecs.open(file_name, "r", "utf-8")    except Exception as e:

print(e)

print("无法打开%s"%file_name)    else:

content = f.read()        # 这里我们假装从mysql获得了数据

data_from_mysql = "我是来自数据库的动态数据......"+'当前的时间为--->%s\n' % time.ctime()        # 将模板中的{content}换成我们的"动态数据"

content = str(re.sub(r"{content}", data_from_mysql, content))

f.close()        return content# web框架入口 def app(environ, start_response):

"""environ包含需要访问的.py文件(模板)的名称, start_response代表来自web框架的函数的引用"""

# 设置返回的状态码信息

status = "200 OK"

# 设置返回的网页类型

response_headers = [('Content-Type', 'text/html;charset=utf-8')]    # 向web框架中定义的函数start_response中传入头信息(状态码,网页类型)

start_response(status, response_headers)

file_name = environ["PATH_INFO"]

content = read_file(file_name)    # 将动态的数据返回给服务器框架

return contentREADME终端运行:

python3 web_server.py 8888 web_frame:app目录样式

AAffA0nNPuCLAAAAAElFTkSuQmCC

AAffA0nNPuCLAAAAAElFTkSuQmCC

小结:

生成动态网页的本质,其实是让程序去替换html中特定部分的内容,换句话说,就是把html页面当成一个没有实际内容的模板,而当用户通过网址访问网页的时候,web框架就把动态的内容填到html模板里面,这样动态生成了带有内容的html网页,web服务器把带有内容的html网页发送给用户浏览器,最后用户收到了含有完整内容的网页,搞定!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_704565.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

博客网站源代码_网站建设技术--WORDPRESS

一、Wordpress是什么?Wordpress是世界上应用最广泛的开源CMS程序。用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站。全球1/4的网站都是用wordpress制作,它起初只是一款个人博客系统,之后逐步演化成一款内容管理系统软件&#x…

无法更改域名 php网页,WordPress更改新域名后网站无法正常运行怎么办?

很多站长在吐槽WordPress站点更改域名后网站无法正常运行,其实这是一个比较简单的问题,一般新手站长会经常遇到这个问题,那么WordPress更改新域名后网站无法正常运行怎么办?方法一:修改wp-config.php1、在wp-config.ph…

Ubuntu系统下的云服务器网站搭建

Ubuntu系统下的云服务器网站搭建(一) 由于近来一直在学网页开发,所以对于WAMP环境下的网站搭建虽不能说多么精通,但是对于其中流程还是比较熟悉的。并且自己也在本机上写了一些有点规模的网站,通过把自己本地的web服务…

作为前端,你不得不知道的SEO

研发的同学,其实很多人并没有深入了解SEO这个概念。在技术博客里,提及这一块的也寥寥无几。我今天就拿自己的经验,简单给大家扫个盲,有什么遗漏的地方,欢迎大家补充。 文字内容有点多,但是干货满满&#xf…

Dfinity入门——配置环境并部署一个简易的网站

环境 我的环境是Mac,如果是win或者Linux可以看官网的部署文档。 1.安装SDK 打开shll终端 #安装SDK sh -ci "$(curl -fsSL https://smartcontracts.org/install.sh)" #安装指定版本 DFX_VERSION0.7.2 sh -ci "$(curl -sSL https://internetcompute…

selenium实现QQ空间和b站这些网站的模拟登录

干了一晚上,对于我这个新手来说太不友好了,要哭了,终于成功了,加油加油,冲冲冲,发布一下给自己留个纪念 我们先说一下思路,我们在使用selenium自动化的时候,其实和你本人打开网站区…

局域网内建立git服务器,并实现不同主机的代码共享(无需通过github网站)

最近需要用MATLAB在远程的服务器上的GPU跑深度学习的程序,但是可视化连接了远程服务器以后,操作非常的卡顿,所以我就在本机上调试好代码,在本机的cpu下跑通了,再搬到服务器上改一下配置用GPU去跑。整个过程&#xff0c…

图片转svg标注_两个免费网站轻松搞定图片文件压缩转化!

关注点击蓝字,关注我吧图片压缩文件转格式两个免费网站轻松搞定免费处理图片文字网站前几天做公号的时候,上传图片遇到了图片过大无法上传的问题。这两个网站可以看做是兄弟俩,今天推荐给大家,省去我们下载安装软件的麻烦。01 I❤…

api服务器开发语言,【API编写】介绍一个国内强大的API接口文档写作网站showdoc - 最好的编程语言 - 博客园...

这几天要写一个接口API文档,经理给我发过来一个,说要弄一个这样的接口文档,我一看,这可麻烦呀,有大纲有详细,我以为要用divcss去一个页面一个页面做呢,这工作量可不小,网站一搜索&am…

网站打不开 换服务器,【图】网站更换服务器打不开—深圳天下信息网

近有一些站长咨询网站更换服务器后打不开,今天小编和大家一起聊一聊!1、网站更换服务器打不开首先考虑的是程序是否完整。更换服务器之前,首先需要完整备份好程序文件,备份之前建议是先关停网站,以免有的数据库文件因为…

从上往下 流式布局_揭秘做好网站结构优化的4步(下)

昨天说了关于优化网站结构的前二条,网站代码的优化和网站目录的优化,虽然这两条很重要,但是这两条还是内部的东西,要真正做好,还需要网站结构优化的内外结合才能做到一个好的优化效果!1. 清晰的url优化&…

大型网站 linux,大型网站架构演变

之前也有一些介绍大型网站架构演变的文章,例如LiveJournal的、ebay的,都是非常值得参考的,不过感觉他们讲的更多的是每次演变的结果,而没有很详细的讲为什么需要做这样的演变,再加上近来感觉有不少同学都很难明白为什么…

主题图标_Avada主题网站favicon图标设置详细图文教程

Avada主题网站favicon图标如何设置?很多网站打开后在浏览器标题栏会发现前面有一个小图标,在浏览器标签页和收藏夹中也能看到。这个标志名叫 favicon图标、ico图标、网站图标。是展示网站个性的logo标识,能够让网站看起来每专业、美观、有个性…

服务器开好服怎么和网站连,vps开服连服务器没反应

vps开服连服务器没反应 内容精选换一换有以下几种现象:将制作好的SD卡插入开发者板并上电后,开发者板LED1与LED2灯状态信息异常。将制作好的SD卡插入开发者板,并通过USB方式连接Ubuntu服务器,上电、开发者板启动完成后&#xff0c…

应用程序池超出其作业限制设置_网站改版注意事项 - 蜘蛛池

最蜘蛛池,快速提高网站收录,百度蜘蛛池、搜狗蜘蛛池、360蜘蛛池、神马蜘蛛池、繁殖池、权重池,欢迎使用。正常的网站页面发展过程中毫无疑问网站是需要做改版的,可是你了解网站改版的一些常见问题吗?还是回答一场说改就改的实际操…

跨境电商自建站后台系统原型rp_没学历做跨境电商好做吗?虾皮shopee开店没有流水怎么办...

(shopee)虾皮刚诞生的时候我就做了,在电商这个行业也有自己的一些经验。经验也许没有其他大卖家丰富,但会将我知道的都进行分享。如果有不懂(shopee)虾皮问题可以我(V:2787823020)。我这里给大家安排一堂直播课,可以系统的帮你解决…

安居客检测到网页抓取_原创内容不收录 解决网站抓取异常的有效分析方法

有的网站明明内容优质原创,用户可以正常访问,但偏偏网络蜘蛛无法正常访问抓取导致无法被收录,搜索结果覆盖率偏低,对搜索引擎和网站都是一种损失,这种情况就是抓取异常。对于大量内容无法正常抓取的网站,搜…

快速排名系统询火星推荐_搜狗网站快速排名系统 - 新站权重如何快速提升

原出处:超级排名系统原文链接:http://www.chaojipaiming.com搜狗网站快速排名系统注册地址 seo.chaojipaiming.com 网站关键词快速排名优化,7-15天关键词排名到首页,PC端和移动端都可以优化,支持百度、搜狗、360、神马…

php网站添加cnzz,cnzz代码添加元素到页面

搜索热词首先在cnzz上注册账号后,他会给你以下代码:document.write(unescape("%3Cspan idcnzz_stat_icon_xxxxxxxxxx%3E%3C/span%3E%3Cscript src" cnzz_protocol "s19.cnzz.com/z_stat.PHP%3Fid%3D1252929438%26show%3Dpic1 typetext/…

Gradle自动化之自动打包并上传到fir测试网站

前言 每个项目都需要测试,没有测试的项目是无法发布到线上的 而由于安卓的碎片化,公司里测试需要测几种不同版本的系统和不同厂商(型号)的手机,所以我平时发的测试包必须放到某个服务器或网站上,通过二维码的方式给测试,这样才能让测试流程更方便 之前的流程都是,先打包,然后…