Python实现简单的Web完整版(一)
在拖了一周之后,今天终于在一个小时之内将一个迷你的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完整版(一)的更多相关文章
- Python 实现简单的 Web
简单的学了下Python, 然后用Python实现简单的Web. 因为正在学习计算机网络,所以通过编程来加强自己对于Http协议和Web服务器的理解,也理解下如何实现Web服务请求.响应.错误处理以及 ...
- python超简单的web服务器
今天无意google时看见,心里突然想说,python做web服务器,用不用这么简单啊,看来是我大惊小怪了. web1.py 1 2 3 #!/usr/bin/python import Simp ...
- python 最简单的web应用(一)
对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. server.py文件 #!/usr/bin/env python # -*- coding: ...
- Python分布式爬虫打造搜索引擎完整版-基于Scrapy、Redis、elasticsearch和django打造一个完整的搜索引擎网站
Python分布式爬虫打造搜索引擎 基于Scrapy.Redis.elasticsearch和django打造一个完整的搜索引擎网站 https://github.com/mtianyan/Artic ...
- 国内某Python大神自创完整版,系统性学习Python
很多小伙伴纠结于这个一百天的时间,我觉得完全没有必要,也违背了我最初放这个大纲上来的初衷,我是觉得这个学习大纲还不错,自学按照这个来也能相对系统的学习知识,而不是零散细碎的知识最后无法整合,每个人的基 ...
- Python实现简单的Web(续)
写的有点乱..希望大神指教~~Python的缩进可真的将我缠了好久,想起我们班大神说缩进也是代码啊..修改之前的代码来显示请求的信息,同时重新整理一下代码: class RequestHandler( ...
- Python实现简单的Web服务器 解析
代码来源https://www.shiyanlou.com/courses/552,对它进行理解,注释 #-*- coding:utf-8 -*- import BaseHTTPServer clas ...
- python一个简单的web服务器和客户端
服务器: 当客户联系时创建一个连接套接字 从这个连接接收HTTP请求(*) 解释该请求所请求的特定文件 从服务器的文件系统获取该文件 并发送文件内容 ...
- 笨办法学python - 专业程序员的养成完整版PDF免费下载_百度云盘
笨办法学python - 专业程序员的养成完整版PDF免费下载_百度云盘 提取码:xaln 怎样阅读本书 由于本书结构独特,你必须在学习时遵守几条规则 录入所有代码,禁止复制粘贴 一字不差地录入代码 ...
随机推荐
- HTML 字符实体 < >: &等
在 HTML 中,某些字符是预留的. 在 HTML 中不能使用小于号(<)和大于号(>),这是因为浏览器会误认为它们是标签. 如果希望正确地显示预留字符,我们必须在 HTML 源代码中使用 ...
- block
不使用__block修饰: ; self.myBlock = ^(){ NSLog(@"block num == %d",num); }; num = ; self.myBlock ...
- java编码
/** * @Comments:default:ISO-8859-1 -> UTF-8 乱码则转码 * @param: str(乱码字符),coding(default:ISO- ...
- ArrayList_HashSet的比较及Hashcode分析
ArrayList_HashSet的比较及Hashcode分析 hashCode()方法的作用 public static void main(String[] args) { Collectio ...
- 批量从jar包中提取pom.xml
将非maven项目转换为maven项目,首要第一步就是提取原工程依赖jar里的pom.xml,拼成<dependency>节点 import java.io.File; import ja ...
- druid连接池获取不到连接的一种情况
数据源一开始配置: jdbc.initialSize=1jdbc.minIdle=1jdbc.maxActive=5 程序运行一段时间后,执行查询抛如下异常: exception=org.mybati ...
- Web Service和WCF的区别。其实二者不属于一个范畴!!!
Web Service和WCF的区别 [1]Web Service:严格来说是行业标准,也就是Web Service 规范. 它有一套完成的规范体系标准,而且在持续不断的更新完善中. 它使用XML扩展 ...
- 制作宅基腐主页 && 制作个人简历--材料:BootStrap
宅基腐主页 主页分为四大板块:导航栏,轮播图,主页内容,相关信息. 导航栏:<nav>标签,class="navbar",navbar-inverse为反色,navba ...
- 12月8日phpcms添加子栏目后的读取
一个栏目下面如果没有子栏目,那么它调用的模板就是列表页模板(及list_为前缀的模板):如果一个栏目下面有子栏目,那么它调用的就是栏目首页模板(category_为前缀的模板). 所以,当你这个栏目添 ...
- [Android]学习笔记Activity_001
操作button的说明 设置button的ID: android:id="@+id/button" 设置button的点击事件 findViewById(R.id.button). ...