在拖了一周之后,今天终于在一个小时之内将一个迷你的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. 15 个 Android 通用流行框架大全(转)

    1. 缓存 DiskLruCache    Java实现基于LRU的磁盘缓存 2.图片加载 Android Universal Image Loader 一个强大的加载,缓存,展示图片的库 Picas ...

  2. bzoj 4003

    左偏树... 打两个标记...和线段树一样,先下放cheng再下放*. 每回合并子树就行了. #include<iostream> #include<cstdio> #incl ...

  3. VirtualBox安装MS-DOS6.22(图文教程)

    最近在读一些计算机发展史之类的文献,总感觉的纸上得来终觉浅,所以打算自己装一个MS-DOS,体验一下远古的操作系统!可以google到MS-DOS的安装文件: 为什么要分成三个呢?可以看到,每个大小都 ...

  4. Struts(View)

    案例:http://blog.csdn.net/jiuqiyuliang/article/details/39061305 减少在运用MVC设计模型来开发Web应用的时间. l  M —— JavaB ...

  5. 【原创】贴个dirtycow(脏牛漏洞)不死机的exploit

    dirtycow官网上几个获得rootshell的exp大都会导致机器死机,在原作者的基础上改进了一下,做个记录: /* * (un)comment correct payload first (x8 ...

  6. OpenStack三种类型的NAT转换

    SNAT SNAT即源网络地址转换,这个NAT路由修改IP包包头中的源IP地址.SNAT功能通常用于让只具有私有IP地址的主机能够访问外网,比如,多个PC使用路由器共享上网,每个PC都配置了内网IP, ...

  7. linux下epoll实现机制

    linux下epoll实现机制 原作者:陶辉 链接:http://blog.csdn.net/russell_tao/article/details/7160071 先简单回顾下如何使用C库封装的se ...

  8. spring统一日志管理,切面(@Aspect),注解式日志管理

    step1 开启切面编程 <!-- 开启切面编程(通过配置织入@Aspectj切面 ) --> <aop:aspectj-autoproxy/> <aop:aspectj ...

  9. Redis实战阅读笔记——第二章

    在性能的要求下,如何获取重构之前的构件

  10. 移动端浏览器body的overflow:hidden并没有什么作用

    今天突然遇到一个问题,使用li模拟select,但是碰到一个很尴尬的问题,给body加了overflow:hidden,但是body并没有禁止滚动条,滚动条依旧顺滑. <!DOCTYPE htm ...