1 静态Web服务器
搭建Python自带的Web服务器:使用 python3 -m http.server 端口号(默认8000)
返回固定页面数据开发步骤:
1 编写一个TCP服务端程序
2 获取浏览器发送的HTTP请求报文数据
3 读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器
4 HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字
import socket
if __name__ == "__main__":
# 1 编写一个TCP服务端程序
tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 创建socket
tcp_server_socket.setsockopt(socket.SOLSOCKET,socket.SO_RESUEADDR,True) # socket复用
tcp_server_socket.bind(("",8080)) # 绑定地址
tcp_server_socket.listen(128) # 设置监听
while True:
# 2 获取浏览器发送的HTTP请求报文数据
client_socket,client_addr = tcp_server.accept() # 建立链接
client_request_data = client_socket.recv(1024)decode() # 获取浏览器请求信息
print(client_request_data)
# 3 读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器
with open("./static/index.html","rb") as f:
file_data = f.read
response_line = "HTTP/1.1 200 OK\r\n"
response_header = "Sercer:pwb\r\n"
response_body = file_data
response_data = (response_line + response_header + "\r\n")
client_socket.send(response_data) # 发生数据
# 4 HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字
cline_socket.close()
注意:
with expression as variable
:expression
是一个返回上下文管理器的表达式,variable
用于保存上下文管理器返回的对象
返回指定页面数据开发步骤:
1 获取用户请求资源的路径
2 根据请求资源的路径,读取指定文件的数据
3 组装指定文件数据的响应报文,发送给浏览器
4 判断请求的文件在服务端不存在,组装404状态的响应报文,发送给浏览器
import socket
if __name__ == "__main__":
# 1 编写一个TCP服务端程序
tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 创建socket
tcp_server_socket.setsockopt(socket.SOLSOCKET,socket.SO_RESUEADDR,True) # socket复用
tcp_server_socket.bind(("",8080)) # 绑定地址
tcp_server_socket.listen(128) # 设置监听
while True:
# 2 获取浏览器发送的HTTP请求报文数据
client_socket,client_addr = tcp_server.accept() # 建立链接
client_request_data = client_socket.recv(1024)decode() # 获取浏览器请求信息
print(client_request_data)
# 获取用户请求资源的路径
request_data = client_request_data.split(" ") # 返回的是一个列表
request_path = request_data[1]
if request_path == "/":
request_path = "/index.html"
# 3 读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器
# 根据请求资源路径,获取指定文件的数据
try:
with open("./static" + request_path,"rb") as f: # 这里是用户输入路径
file_data = f.read
except Exception as e:
# 返回404错误数据
response_line = "HTTP/1.1 404 Not Found\r\n"
response_header = "Sercer:pwb\r\n"
response_body = "404 Not Found sorry"
# 组装指定文件数据的响应报文,发送给浏览器
response_data = (response_line + response_header + "\r\n" + response.body).encode
client_socket.send(response_data) # 发生数据
else:
response_line = "HTTP/1.1 200 OK\r\n"
response_header = "Sercer:pwb\r\n"
response_body = file_data
# 组装指定文件数据的响应报文,发送给浏览器
response_data = (response_line + response_header + "\r\n").emcode() + response.body
client_socket.send(response_data) # 发数据
finally:
# 4 HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字
cline_socket.close()
静态Web服务器—多任务版
当客户端和服务端建立连接成功,创建子线程,使用子线程专门处理客户端的请求,防止主线程阻塞
import socket
import threading
def handle_client_request(client_socket):
client_request_data = client_socket.recv(1024)decode() # 获取浏览器请求信息
print(client_request_data)
# 获取用户请求资源的路径
request_data = client_request_data.split(" ") # 返回的是一个列表
request_path = request_data[1]
# 判断客户端是否关闭
if len(request_data) == 1:
client_socket.close()
return
if request_path == "/":
request_path = "/index.html"
# 3 读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器
# 根据请求资源路径,获取指定文件的数据
try:
with open("./static" + request_path,"rb") as f: # 这里是用户输入路径
file_data = f.read
except Exception as e:
# 返回404错误数据
response_line = "HTTP/1.1 404 Not Found\r\n"
response_header = "Sercer:pwb\r\n"
response_body = "404 Not Found sorry"
# 组装指定文件数据的响应报文,发送给浏览器
response_data = (response_line + response_header + "\r\n" + response.body).encode
client_socket.send(response_data) # 发生数据
else:
response_line = "HTTP/1.1 200 OK\r\n"
response_header = "Sercer:pwb\r\n"
response_body = file_data
# 组装指定文件数据的响应报文,发送给浏览器
response_data = (response_line + response_header + "\r\n").emcode() + response.body
client_socket.send(response_data) # 发数据
finally:
# 4 HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字
cline_socket.close()
if __name__ == "__main__":
# 1 编写一个TCP服务端程序
tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 创建socket
tcp_server_socket.setsockopt(socket.SOLSOCKET,socket.SO_RESUEADDR,True) # socket复用
tcp_server_socket.bind(("",8080)) # 绑定地址
tcp_server_socket.listen(128) # 设置监听
while True:
# 2 获取浏览器发送的HTTP请求报文数据
client_socket,client_addr = tcp_server.accept() # 建立链接
# 创建子线程
sub_thread = threading.Thread(target=handler_client_request,args=(client_socket,))
sub_thread.start()
静态Web服务器—面向对象开发
1 把提供服务的Web服务器抽象成一个类(HTTPWebServer):class HttpWebServer
2 提供Web服务器的初始化方法,在初始化方法里面创建Socket对象:def __init__(self)
3 提供一个开启Web服务器的方法,让Web服务器处理客户端请求操作:def star(self)
import socket
import threading
class HttpWebServer:
def __init__(self):
# 1 编写一个TCP服务端程序
self. tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 创建socket
self. tcp_server_socket.setsockopt(socket.SOLSOCKET,socket.SO_RESUEADDR,True) # socket复用
self. tcp_server_socket.bind(("",8080)) # 绑定地址
self. tcp_server_socket.listen(128) # 设置监听
def handle_client_request(self,client_socket):
client_request_data = client_socket.recv(1024)decode() # 获取浏览器请求信息
print(client_request_data)
# 获取用户请求资源的路径
request_data = client_request_data.split(" ") # 返回的是一个列表
request_path = request_data[1]
# 判断客户端是否关闭
if len(request_data) == 1:
client_socket.close()
return
if request_path == "/":
request_path = "/index.html"
# 3 读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器
# 根据请求资源路径,获取指定文件的数据
try:
with open("./static" + request_path,"rb") as f: # 这里是用户输入路径
file_data = f.read
except Exception as e:
# 返回404错误数据
response_line = "HTTP/1.1 404 Not Found\r\n"
response_header = "Sercer:pwb\r\n"
response_body = "404 Not Found sorry"
# 组装指定文件数据的响应报文,发送给浏览器
response_data = (response_line + response_header + "\r\n" + response.body).encode
client_socket.send(response_data) # 发生数据
else:
response_line = "HTTP/1.1 200 OK\r\n"
response_header = "Sercer:pwb\r\n"
response_body = file_data
# 组装指定文件数据的响应报文,发送给浏览器
response_data = (response_line + response_header + "\r\n").emcode() + response.body
client_socket.send(response_data) # 发数据
finally:
# 4 HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字
cline_socket.close()
def star(self):
while True:
# 2 获取浏览器发送的HTTP请求报文数据
client_socket,client_addr = self. tcp_server.accept() # 建立链接
# 创建子线程
sub_thread = threading.Thread(target=self.handler_client_request,args=(client_socket,))
sub_thread.start()
if __name__ == '__main__':
# 创建服务器对象
my_web_server = HttpWebServer()
my_web_server.start()
静态Web服务器—命令行启动动态绑定端口号
1 获取执行python程序的终端命令行参数
2 判断参数的类型,设置端口号必须是整型
3 给Web服务器类的初始化方法添加一个端口号参数,用于绑定端口号
import socket
import threading
import sys
class HttpWebServer:
def __init__(self,port):
# 1 编写一个TCP服务端程序
self. tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 创建socket
self. tcp_server_socket.setsockopt(socket.SOLSOCKET,socket.SO_RESUEADDR,True) # socket复用
self. tcp_server_socket.bind(("",port)) # 绑定地址
self. tcp_server_socket.listen(128) # 设置监听
def handle_client_request(self,client_socket):
client_request_data = client_socket.recv(1024)decode() # 获取浏览器请求信息
print(client_request_data)
# 获取用户请求资源的路径
request_data = client_request_data.split(" ") # 返回的是一个列表
request_path = request_data[1]
# 判断客户端是否关闭
if len(request_data) == 1:
client_socket.close()
return
if request_path == "/":
request_path = "/index.html"
# 3 读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器
# 根据请求资源路径,获取指定文件的数据
try:
with open("./static" + request_path,"rb") as f: # 这里是用户输入路径
file_data = f.read
except Exception as e:
# 返回404错误数据
response_line = "HTTP/1.1 404 Not Found\r\n"
response_header = "Sercer:pwb\r\n"
response_body = "404 Not Found sorry"
# 组装指定文件数据的响应报文,发送给浏览器
response_data = (response_line + response_header + "\r\n" + response.body).encode
client_socket.send(response_data) # 发生数据
else:
response_line = "HTTP/1.1 200 OK\r\n"
response_header = "Sercer:pwb\r\n"
response_body = file_data
# 组装指定文件数据的响应报文,发送给浏览器
response_data = (response_line + response_header + "\r\n").emcode() + response.body
client_socket.send(response_data) # 发数据
finally:
# 4 HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字
cline_socket.close()
def star(self):
while True:
# 2 获取浏览器发送的HTTP请求报文数据
client_socket,client_addr = self. tcp_server.accept() # 建立链接
# 创建子线程
sub_thread = threading.Thread(target=self.handler_client_request,args=(client_socket,))
sub_thread.start()
def main():
# 获取执行python程序的终端命令行参数
print(sys.argv)
if len(sys.argv) != 2:
print('格式错误 pyhton3 xxx.py 9090')
return
# 判断参数的类型,设置端口号必须是整型
if not sys.argv[1].isdigit(): # isdigit():判断参数是否为整型
print('格式错误 pyhton3 xxx.py 9090')
return
# 创建服务器对象
# 给Web服务器类的初始化方法添加一个端口号参数,用于绑定端口号
my_web_server = HttpWebServer(port)
my_web_server.start()
if __name__ == '__main__':
main()
2 闭包
2.1 函数参数
函数名
存放的是函数所在空间地址,函数名()
执行函数名所存放空间地址中的代码
def func01():
print('nihao')
def foo(func):
func()
# 调用函数 参数就是函数func01
foo(func01)
闭包:在函数嵌套的前提
下,内部函数使用了外部函数的变量,
并且外部函数返回了内部函数
,我们把这个使用外部函数变量的内部函数称为闭包
def func_out(num1): # 这就是一个闭包
def func_inner(num2):
num = num1 + num2
return func_inner
f = func_out(10) # 创建闭包实例
f(1) # 返回结果是:11
注意:
1 通过f=func_out(10)创建闭包,实际上f() 等价于 内部函数func_inner()
,即调用闭包相当于调用内部函数
2 利用 nonlocal 变量
,可以修改外部函数的变量
def func_out(num1): # 这就是一个闭包
def func_inner(num2):
nunlaocal num1 # 声明外部函数变量
num1 = num2 + 10
print(num1)
dun_inner(10)
print(num1)
return func_inner
func_out(10) # 返回结果是:10,20
3 装饰器
装饰器:在不改变原有函数的源代码的情况下,给函数增加新的功能,本质是闭包
装饰器语法糖用法:
def check(fn):
def inner():
print('登录验证...')
fn()
return inner
# 解释器遇到 @check 会立即执行comment = check(comment)
@check
def comment(): # 需要被装饰的函数
print('发表评论')
# 使用装饰器装饰函数,增加一个登录功能
# comment = check(comment)
comment() # 返回结果是:登录验证...发表评论
装饰器实现函数执行时间统计
import time
def get_time(fn):
def inner():
start = time.time()
fn()
end = time.time()
print('时间:',end - start)
return inner
@get_time
def func(): # 需要被装饰的函数
for i in range(100000):
print(i)
func() # 返回结果是:时间:0.2xxs
带有参数的装饰器
def logging(fn): # fn = sum_num
def inner(a,b):
fn(a,b)
return inner # sum_num = inner
@logging
def sun_num(a,b): # 需要被装饰的函数
result = a + b
print(result)
sum_num(1,2) # 返回结果是:3
装饰带有返回值的函数
def logging(fn): # fn = sum_num
def inner(a,b):
result = fn(a,b)
print(result)
return inner # sum_num = inner
@logging
def sun_num(a,b): # 需要被装饰的函数
result = a + b
print(result)
result = sum_num(1,2)
print(result) # 返回结果是:3
通用装饰器—装饰带有不定长参数的函数
def logging(fn): # fn = sum_num
def inner(*args,**kwargs):
result = fn(*args,**kwargs)
print(result)
return inner # sum_num = inner
@logging
def sun_num(*args,**kwargs): # 需要被装饰的函数
print(*args,**kwargs)
sum_num(1,2,3,age="18")
多个装饰器装饰一个函数
def check1(fn1):
def inner1():
print('登录验证1')
fn1()
return inner1
def check1(fn2):
def inner2():
print('登录验证1')
fn2()
return inner2
@check1
@check2
def comment(): # 需要被装饰的函数
print('发表评论')
comment() # 返回结果是:登录验证1 登录验证2 发表评论
带有参数的装饰器
def logging(flag):
def decorator(fn): # 外部函数只允许有fn一个参数
def inner(num1,num2):
if flag == "+":
print('正在进行加法运算')
elif flag == "-":
print('正在进行减法运算')
result = fn(num1,num2)
return result
return inner
return decorator
@logging('+') # 此处 + 是装饰器的参数
def add(a,b):
print a + b
result = add(1,3)
print(result)
类装饰器
__call__方法
:一个类里面一旦实现了__call__
方法,那么这个类创建的对象就是一个可调用对象,可以像调用函数一样进行调用
class Check(object):
def __call__(self,*args,**kwargs):
print('我是call')
c = Check()
c() # 返回结果是:我是call
class Check(object):
def __init__(self,fn): # fn = comment
self.__fn = fn # 私有属性
def __call__(self,*args,**kwargs):
print('登录')
self.__fn() # comment()
@Check # comment= Ckeck(comment)
def comment:
print('发表评论')
comment()
esult = add(1,3)
print(result)
类装饰器
__call__方法
:一个类里面一旦实现了__call__
方法,那么这个类创建的对象就是一个可调用对象,可以像调用函数一样进行调用
class Check(object):
def __call__(self,*args,**kwargs):
print('我是call')
c = Check()
c() # 返回结果是:我是call
class Check(object):
def __init__(self,fn): # fn = comment
self.__fn = fn # 私有属性
def __call__(self,*args,**kwargs):
print('登录')
self.__fn() # comment()
@Check # comment= Ckeck(comment)
def comment:
print('发表评论')
comment()