2024年最新【面试必会,Python写一个简易的web服务器(1),Python面试项目

收集整理了一份《2024年最新Python全套学习资料》免费送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img



既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Python知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来

如果你需要这些资料,可以添加V无偿获取:hxbc188 (备注666)
img

正文

当然,如果 "?“和”&“是特殊字符,必须有方法避开他们,就是必须有个方法来把一个双引号字符放进用双引号限定的字符串内。 URL编码标准用%后面跟着2位的代码代表特殊字符,并以”+"字符代替空格。因此,搜索Google“grade= A+”(有空格),我们应该使用URL http://www.google.ca/search?q=grade+%3D+A%2B。

打开sockets,构建HTTP请求,解析响应是乏味的,所以大多数人使用库来完成大部分的工作。 Python提供了这样一个称作urllib2的库(因为它是一个较早版本的库urllib的升级版),但它暴露了很多大多数人永远不想关注的底层编码。Requests库比urllib2更容易使用。下面是一个使用它从AOSA图书网站下载页面的例子:

request.get发送一个HTTP GET请求到服务器,并返回一个包含响应的对象。该对象的status_code成员是响应的状态码;它的content_length成员是响应数据中的字节数,text是实际的数据(在这种情况下,是一个HTML页面)。

hello,web

现在,我们准备写我们的第一个简单的Web服务器。基本思想非常简单:

1.等待有人来连接我们的服务器,发送HTTP请求;

2.解析请求;

3.找出它的要求;

4.获取数据(或动态生成它);

5.把数据格式化为HTML;

6.回发。

从一个应用程序到另一个,步骤1,2和6是相同的,所以Python标准库有一个名为BaseHTTPServer的模块为我们做这些步骤。我们只需要关注步骤3-5,这是我们在下面的小程序里做的:

库的BaseHTTPRequestHandler类负责解析传入的HTTP请求,并判断它含有什么方法。如果方法是GET,类调用一个名为do_GET的方法。我们的RequestHandler类覆盖此方法来动态生成一个简单的页面:文本被存储在类级别的变量Page中,在我们发送一个200响应码后被发回客户端,Content-Type头文件,告诉客户端把我们的数据和页面长度翻译为HTML格式。 (调用end_headers方法插入空白行,来区分头文件和页面本身。)

但RequestHandler并不是故事的全部:我们还需要最后三行来使服务器开始运行。其中第一行定义服务器的地址为一个元组:空字符串意味着“在当前计算机上运行”,8080是端口号。然后,我们创建一个BaseHTTPServer.HTTPServer的实例,实例中含有服务器地址和我们的请求处理类作为参数的名称,然后要求它永久运行(这实际上意味着,直到我们使用Control-C杀死它才停止运行)。

如果我们在命令行中运行这个程序,它不显示任何内容:

$ python server.py

然后如果我们用我们的浏览器访问http://localhost:8080,那么,在浏览器中我们得到这样的内容:

Hello, web!

在我们的shell中是这样的内容:

127.0.0.1 - - [24/Feb/2014 10:26:28] “GET / HTTP/1.1” 200 -

127.0.0.1 - - [24/Feb/2014 10:26:28] “GET /favicon.ico HTTP/1.1” 200 -

第一行是直观的:因为我们没有要求特定文件,我们的浏览器就要求"/"(服务器提供所有的根目录)。出现第二行是因为我们的浏览器会自动发送第二个请求来请求一个名为/favicon.ico的图像文件,如果图像文件存在,它会在地址栏显示为一个图标。

显示数值

让我们修改我们的Web服务器来显示一些包含在HTTP请求中的值。 (在调试的时候,我们会相当频繁的做这个,所以我们不妨做一些练习)。为了保持我们的代码简洁,我们将把创建页面和发送页面分开:

send_page我们之前几乎都有的:

因为我们要显示的页面模板仅仅是一串字符串,字符串包括带有一些格式占位符的HTML表:

填充方法是:

该程序的主体是不变的:和以前一样,它创建了一个HTTPServer类的实例,实例中含有一个地址和作为参数的请求处理器,然后永久服务请求。如果我们运行它,并从浏览器中发送一个请求:http://localhost:8080/something.html,我们得到:

Date and time Mon, 24 Feb 2014 17:17:12 GMT

Client host 127.0.0.1

Client port 54548

Command GET

Path /something.html

请注意,我们没有收到一个404错误,即使something.html页面文件在磁盘上不存在。这是因为Web服务器只是一个程序,当它获得一个请求时,它可以做任意想做的事:发回在先前的请求里被命名的文件、提供随机选择的一个维基百科页面,或我们编写的任意的东西。

提供静态页面服务

明显的,下一步是从磁盘启动服务页面,而不是动态生成。我们会通过改写do_GET来开始:

该方法假定提供Web服务器运行目录下的任何文件都是被允许的(使用os.getcwd函数来获得当前运行目录)。它把当前运行目录与URL提供的路径(库将路径自动放入self.path中,并始终以 “/”开头)相结合,来获得用户想要文件的路径。

如果路径不存在,或者如果它不是一个文件,该方法通过抛出和捕获异常报告错误。如果路径匹配一个文件,在另一方面,它调用一个帮助者方法命名为handle_file来读取和返回内容。这种方法只会读取文件,并使用我们现有的send_content将其发送回客户端:

请注意,我们在以二进制模式打开文件—the “b” in “rb”—,因此Python不会帮我们去通过改变字节序列而使其看起来像一个Windows结束行。还需要注意的是在现实生活中,当为它服务时,读取整个文件到内存是个坏主意,该文件可能是数千兆字节的视频数据。处理这种情况不在本章的范围之内。

为了完成这个类,我们需要编写错误处理方法和错误报告页面模板:

这个程序可用,但前提是我们别太细看。问题是,它总是返回状态码200,即使当被请求的页面不存在。在这种情况下,发回的页面包含一个错误信息,但由于我们的浏览器读不懂英文,它不知道该请求其实失败了。为了说清楚这点,我们需要按如下修改handle_error和send_content:

请注意,当找不到文件时我们不抛出ServerException,而是产生一个错误页面。ServerException是为了传递服务器代码中的内部错误信号,即,我们弄错了某东西。在另一方面,通过handle_error创建的错误页面,出现在用户犯了一些错误的时候,即,给我们发送了一个不存在的文件的URL。(1)

列出目录

作为我们的下一步,当URL中的路径是一个目录而不是文件时,我们可以教Web服务器显示目录列表。我们甚至可以更进一步,让它在那个目录中以index.html文件显示,并且文件不存在时,只显示目录内容的列表。

但是,把这些规则写进do_GET将是一个错误,因为方法最终将会成为长长一大团控制特定行为的if声明。正确的解决办法是退后一步,解决一般性问题,指出如何处理URL。这里是重写的do_GET方法:

第一步是一样的:指出被请求的东西的全路径。尽管在那之后,代码看起来相当不同。该版本遍历一组存储在列表中的cases类来代替一堆的内联测试。每个case是一个有两个方法的对象:方法test,它告诉我们它是否能够处理请求,方法act,它实际上采取了一些行动。我们一找到正确的case,我们马上让它处理请求并跳出循环。

这三个case类复制我们之前服务器的行为:

如下是我们如何在RequestHandler类的顶部构建case handlers的列表:

现在,表面上看这使得我们的服务器更加复杂,而不是更简单:该文件已经从74行增加至99行,并且有额外的间接寻址,没有增加任何新的功能。这样做的好处是,当我们回到那个本章开始的任务,如果有文件的话,就尝试教我们的服务器来提供index.html页面作为目录,如果没有的话,就提供目录的列表。前者的handler程序是:

在这里,帮助者方法index_path构建index.html文件的路径;把它放进case handler中防止主函数RequestHandler杂乱。 test检查路径是否是包含index.html的目录,act要求主函数请求处理器提供该页面。

唯一需要RequestHandler改变的是把一个case_directory_index_file对象添加到我们的Cases列表中:

如果目录中不包含index.html页怎么办呢?test方法和上面战略性插入not相同,但act方法该怎么样呢?他该怎么做?

我们似乎陷入了困境。从逻辑上讲,act方法应创建并返回目录列表,但是我们现有的代码不允许:RequestHandler.do_GET调用了act,却并不想要或处理返回值。现在,让我们在RequestHandler里添加一个方法来生成一个目录列表,并从case handler的act方法调用该方法:

CGI协议

当然,大多数人都不会想要编辑他们的网络服务器的源代码来增加新的功能。为了从这种不得不这么做的泥沼中解脱出来,服务器一直支持一个叫做通用网关接口(CGI)的机制,这为Web服务器为了满足请求去运行外部程序提供了一种标准方法。

例如,假设我们希望服务器能在HTML页面中显示本地时间。我们在只有几行代码的独立的程序中就可以做到:

为了使Web服务器运行该程序,我们添加如下的case handler:

test方法很简单:文件路径是以.py结尾吗?如果是,RequestHandler运行此程序。

最后

不知道你们用的什么环境,我一般都是用的Python3.6环境和pycharm解释器,没有软件,或者没有资料,没人解答问题,都可以免费领取(包括今天的代码),过几天我还会做个视频教程出来,有需要也可以领取~

给大家准备的学习资料包括但不限于:

Python 环境、pycharm编辑器/永久激活/翻译插件

python 零基础视频教程

Python 界面开发实战教程

Python 爬虫实战教程

Python 数据分析实战教程

python 游戏开发实战教程

Python 电子书100本

Python 学习路线规划

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

如果你需要这些资料,可以添加V无偿获取:hxbc188 (备注666)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
size_16,color_FFFFFF,t_70)

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

如果你需要这些资料,可以添加V无偿获取:hxbc188 (备注666)
[外链图片转存中…(img-25Kzykn1-1713853705753)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值