在拖了一周之后,今天终于在一个小时之内将一个迷你的Web写出来了,最近改其它项目的bug头好大,但是好喜欢这样的状态。

黑色的12月,所有的任务都聚集在了12月,然后期末考试也顾不上好好复习了,但是但是,我要一步步的把手上的项目做出来!!!

回归正题了:这次的Python网络编程也是速成的,对于Python只是看了大体的语言框架后就直接上手写网络编程部分了,有错希望前辈指正~~

Python版本:2.7

IDE:PyCharm

接着前面几篇基础的这次主要修改了下面的部分:

最终完成的是下面的结构:

一、响应静态页面

所以这一步就该处理静态页面了,处理静态页面就是根据请求的页面名得到磁
盘上的页面文件并返回。
在当前目录下创建新文件 plain.html,这是测试用的静态页面

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Plain Page</title>
</head>
<body>
<p>HAha, this is plain page...</p>
</body>
</html>

  在 server.py 中导入需要的库

import sys, os, BaseHTTPServer
为服务器程序写一个异常类

class ServerException(Exception):
''' 服务器内部错误 '''
pass  重写  do_GET 函数
# deal with a request
def do_GET(self):
try:
full_path = os.getcwd() + self.path if not os.path.exists(full_path):
raise ServerException("'{0}' not found".format(self.path))
elif os.path.isfile(full_path):
self.handle_file(full_path)
# 访问根路径
elif os.path.isdir(full_path):
# fullPath = os.path.join(fullPath, "index.html")
full_path += "index.html"
if os.path.isfile(full_path):
self.handle_file(full_path)
else:
raise ServerException("'{0}' not found".format(self.path))
else:
raise ServerException("Unknown object '{0}'".format(self.path))
except Exception as msg:
self.handle_error(msg)

首先看完整路径的代码, os.getcwd() 是当前的工作目录, self.path 保存了请求的相对路径, RequestHandler 是继承自 BaseHTTPRequestHandler 的,它已经

将请求的相对路径保存在 self.path 中了。
编写文件处理函数和错误处理函数:

# page model
Page = '''
<html>
<body>
<table border=2s>
<tr> <td>Header</td> <td>Value</td> </tr>
<tr> <td>Date</td><td> and time</td> <td>{date_time}</td> </tr>
<tr> <td>Client host</td> <td>{client_host}</td> </tr>
<tr> <td>Client port</td> <td>{client_port}</td> </tr>
<tr> <td>Command</td> <td>{command}</td> </tr>
<tr> <td>Path</td> <td>{path}</td> </tr>
</table>
</body>
</html>
'''
Error_Page = """\
<html>
<body>
<h1>Error accessing {path}</h1>
<p>{msg}</p>
</body>
</html>
""" def handle_error(self, msg):
content = self.Error_Page.format(path=self.path, msg=msg)
self.send_content(content, 404) def handle_file(self, full_path):
# 处理 python 脚本
if full_path.endswith('.py'):
# data 为脚本运行后的返回值
data = subprocess.check_output(['python', full_path])
self.send_content(data)
return
try:
with open(full_path, 'rb') as reader:
content = reader.read()
self.send_content(content)
except IOError as msg:
msg = "'{0}' cannot be read: {1}".format(self.path, msg)
self.handle_error(msg) 看下效果喽:

再测试一下错误的路径:

上面也是返回了错误页面

但同时如果用 postman 观察的话,返回的是200 状态码,要不要希望它能够返回 404呢,哈哈,所以还需要修改一

下 handle_error 与 send_content 函数

这次的话如果在输入不存在的 url 就能返回 404 状态码了。

在根 url 显示首页内容

在工作目录下添加 index.html 文件

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h1>Index Page </h1>
<p>I love Python, to be honest</p> </body>
</html>

  此时do_GET函数也要修改下:

    def do_GET(self):
try:
full_path = os.getcwd() + self.path if not os.path.exists(full_path):
raise ServerException("'{0}' not found".format(self.path))
elif os.path.isfile(full_path):
self.handle_file(full_path)
# 访问根路径
elif os.path.isdir(full_path):
# fullPath = os.path.join(fullPath, "index.html")
full_path += "index.html"
if os.path.isfile(full_path):
self.handle_file(full_path)
else:
raise ServerException("'{0}' not found".format(self.path))
else:
raise ServerException("Unknown object '{0}'".format(self.path))
except Exception as msg:
self.handle_error(msg)
看看效果了:

.CGI 协议

有时候呢,大部分人是不希望每次都给服务器加新功能时都要到服务器的源代码里进行
修改。所以,如果程序能独立在另一个脚本文件里运行那就再好不过啦。下面实现CGI:

如下面在 html 页面上显示当地时间。
创建新文件 time.py

from datetime import datetime

print '''\
<html>
<body>
<p>Generated {0}</p>
</body>
</html>'''.format(datetime.now())

  导入 import subprocess,这是一个在程序中生成子进程的模块,它是对fork(),exec()等函数做了封装

【不过目前我还没有掌握,学长说以后会在操作系统课程中学到~~~】

修改 handleFile()函数

    def handle_file(self, full_path):
# 处理 python 脚本
if full_path.endswith('.py'):
# data 为脚本运行后的返回值
data = subprocess.check_output(['python', full_path])
self.send_content(data)
return
try:
with open(full_path, 'rb') as reader:
content = reader.read()
self.send_content(content)
except IOError as msg:
msg = "'{0}' cannot be read: {1}".format(self.path, msg)
self.handle_error(msg)
看看效果了:

 

w(゚Д゚)w。

它成功的显示了现在的时间,看到后不禁要担心过会儿一定不能再被教学区的阿姨赶出自习室了。。

不不,又没有去跑步啊。。。

上面的功能都是在学长写的文档的指导下做了自己的修改一行一行实现的~~

下篇还会在此基础上对BaseHTTPServer.HTTPServer,

BaseHTTPServer.BaseHTTPRequestHandler 再学习去实现, 现在只是实现了最基
础的部分。

后面完整的代码如下:

# -*-coding:utf-8 -*-
import BaseHTTPServer
import os
import subprocess class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
"""dealt with and return page"""
# page model
Page = '''
<html>
<body>
<table border=2s>
<tr> <td>Header</td> <td>Value</td> </tr>
<tr> <td>Date</td><td> and time</td> <td>{date_time}</td> </tr>
<tr> <td>Client host</td> <td>{client_host}</td> </tr>
<tr> <td>Client port</td> <td>{client_port}</td> </tr>
<tr> <td>Command</td> <td>{command}</td> </tr>
<tr> <td>Path</td> <td>{path}</td> </tr>
</table>
</body>
</html>
'''
Error_Page = """\
<html>
<body>
<h1>Error accessing {path}</h1>
<p>{msg}</p>
</body>
</html>
""" def handle_error(self, msg):
content = self.Error_Page.format(path=self.path, msg=msg)
self.send_content(content, 404) def handle_file(self, full_path):
# 处理 python 脚本
if full_path.endswith('.py'):
# data 为脚本运行后的返回值
data = subprocess.check_output(['python', full_path])
self.send_content(data)
return
try:
with open(full_path, 'rb') as reader:
content = reader.read()
self.send_content(content)
except IOError as msg:
msg = "'{0}' cannot be read: {1}".format(self.path, msg)
self.handle_error(msg) # deal with a request
def do_GET(self):
try:
full_path = os.getcwd() + self.path if not os.path.exists(full_path):
raise ServerException("'{0}' not found".format(self.path))
elif os.path.isfile(full_path):
self.handle_file(full_path)
# 访问根路径
elif os.path.isdir(full_path):
# fullPath = os.path.join(fullPath, "index.html")
full_path += "index.html"
if os.path.isfile(full_path):
self.handle_file(full_path)
else:
raise ServerException("'{0}' not found".format(self.path))
else:
raise ServerException("Unknown object '{0}'".format(self.path))
except Exception as msg:
self.handle_error(msg) @property
def create_page(self):
values = {
'date_time': self.date_time_string(),
'client_host': self.client_address[0],
'client_port': self.client_address[1],
'command': self.command,
'path': self.path
}
page = self.Page.format(**values)
return page
pass def send_content(self, content, status=200):
self.send_response(status) self.send_header("Content-type", "text/html")
self.send_header("Content-Length", str(len(content)))
self.end_headers()
self.wfile.write(content)
pass class ServerException(Exception):
pass
if __name__ == '__main__':
server_address = ('127.0.0.1', 5555)
server = BaseHTTPServer.HTTPServer(server_address, RequestHandler)
server.serve_forever()

  

 

Python实现简单的Web完整版(一)的更多相关文章

  1. Python 实现简单的 Web

    简单的学了下Python, 然后用Python实现简单的Web. 因为正在学习计算机网络,所以通过编程来加强自己对于Http协议和Web服务器的理解,也理解下如何实现Web服务请求.响应.错误处理以及 ...

  2. python超简单的web服务器

    今天无意google时看见,心里突然想说,python做web服务器,用不用这么简单啊,看来是我大惊小怪了. web1.py   1 2 3 #!/usr/bin/python import Simp ...

  3. python 最简单的web应用(一)

    对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. server.py文件 #!/usr/bin/env python # -*- coding: ...

  4. Python分布式爬虫打造搜索引擎完整版-基于Scrapy、Redis、elasticsearch和django打造一个完整的搜索引擎网站

    Python分布式爬虫打造搜索引擎 基于Scrapy.Redis.elasticsearch和django打造一个完整的搜索引擎网站 https://github.com/mtianyan/Artic ...

  5. 国内某Python大神自创完整版,系统性学习Python

    很多小伙伴纠结于这个一百天的时间,我觉得完全没有必要,也违背了我最初放这个大纲上来的初衷,我是觉得这个学习大纲还不错,自学按照这个来也能相对系统的学习知识,而不是零散细碎的知识最后无法整合,每个人的基 ...

  6. Python实现简单的Web(续)

    写的有点乱..希望大神指教~~Python的缩进可真的将我缠了好久,想起我们班大神说缩进也是代码啊..修改之前的代码来显示请求的信息,同时重新整理一下代码: class RequestHandler( ...

  7. Python实现简单的Web服务器 解析

    代码来源https://www.shiyanlou.com/courses/552,对它进行理解,注释 #-*- coding:utf-8 -*- import BaseHTTPServer clas ...

  8. python一个简单的web服务器和客户端

    服务器:      当客户联系时创建一个连接套接字      从这个连接接收HTTP请求(*)      解释该请求所请求的特定文件      从服务器的文件系统获取该文件      并发送文件内容 ...

  9. 笨办法学python - 专业程序员的养成完整版PDF免费下载_百度云盘

    笨办法学python - 专业程序员的养成完整版PDF免费下载_百度云盘 提取码:xaln  怎样阅读本书 由于本书结构独特,你必须在学习时遵守几条规则 录入所有代码,禁止复制粘贴 一字不差地录入代码 ...

随机推荐

  1. 【转】OpenGL超级宝典笔记——纹理映射Mipmap

    原文地址 http://my.oschina.net/sweetdark/blog/177812 , 感谢作者,若非法转载请联系本人. 目录[-] Mipmapping Mipmap过滤 构建Mip层 ...

  2. mongodb未授权访问漏洞

    catalogue . mongodb安装 . 未授权访问漏洞 . 漏洞修复及加固 . 自动化检测点 1. mongodb安装 apt-get install mongodb 0x1: 创建数据库目录 ...

  3. SQL链接服务器

    最近做项目,需要对两个数据库进行同步操作,所以采用在Server SQL中建立链接服务器方式实现. 链接服务器,可以直接访问/操作其他服务器上的数据库表. 1.连接SQL Server链接服务器 EX ...

  4. nginx-1.8.0 rpm包制作

    1.安装rpm-build # yum install rpm-build 2.创建制作RPM包目录 # cat /root/.rpmmacros %_topdir /root/rpmbuild %_ ...

  5. 按日期切割nginx访问日志--及性能优化

    先谈下我们需求,一个比较大的nginx访问日志,根据访问日期切割日志,保存在/tmp目录下. 测试机器为腾讯云机子,单核1G内存.测试日志大小80M. 不使用多线程版: #!/usr/bin/env ...

  6. EditPlus-CN使用总结

    EditPlus-CN使用总结 --------------- 注册名:Free User注册码:6AC8D-784D8-DDZ95-B8W3A-45TFA ---------------- 1.如何 ...

  7. MVC

    PureMVC--一款多平台MVC框架 http://www.jianshu.com/p/47deaced9eb3 MVC,MVP 和 MVVM 的图示 http://www.ruanyifeng.c ...

  8. c语言一些知识点的记录

    1.extern关键字 extern关键字可以置于变量或者函数前面,用于告诉编译器此变量或函数定义于其他的模块.

  9. 学习CodeIgniter框架之旅(二)继承自定义类

    在很多情况下,框架类并不能满足项目的需求,这时候需要程序要自定义一些类,比如说基类等等,对比了TP框架,CI框架目前好像还没加入命名空间,这点TP做得比较好,不用特殊的处理就可以随便继承自定义的类,只 ...

  10. Eclipse MySQL Hibernate 中文乱码问题

    如果是Eclipse的问题,那就对以下各项进行设置,即可排除问题. 设置eclipse相关编码为UTF-8: 修改工作区默认编码,位置:windows--perferences--general--w ...