python框架之虚拟环境配置

python框架之虚拟环境配置

1. web框架

web服务器:web服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序。目前最主流的三个web服务器是Apache、Nginx。IIS。
web框架:是一种开发框架,用来支持动态网站、网络应用程序及网络服务的开发
WSGI:web服务器网关接口(python Web Server Gateway Interface),是为Python语言定义的web服务器和web应用程序或框架之间的一种简单而通用的接口
静态资源:不需要经常变化的资源,这种资源web服务器可以提前准备好,比如:png/jpg/css/js等文件
动态资源:和静态资源相反,这种资源会经常变化,web服务器无法提前准备好,需要web框架来帮web服务器进行准备,在这里服务器可以把.html的资源请求认为是动态资源请求交由web框架进行处理

流程图

2. 开发自己的简单web框架

  • 如果请求资源路径的后缀名是.html则是动态资源请求,让web框架进行处理
  • 静态资源请求,让web服务器进行处理

1、开发web服务器主体程序

  1. 接收客户端HTTP请求(TCP协议)
  2. 判断请求是否是静态资源还是动态资源
  3. 静态资源的处理
  4. 动态资源的处理
  5. 关闭web服务器
    my_web.py
import socket
import threading
import MyFramework
# 开发自己的web服务器主类
class MyHttpWebServer(object):
    def __init__(self,port):
        # 创建http服务的套接字
        server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        #设置端口号复用,程序退出之后不需要等待几分钟,直接释放端口
        server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
        server_socket.bind(('',port))
        server_socket.listen(128)
        self.server_socket = server_socket
    # 处理浏览器请求的函数
    @staticmethod
    def handle_browser_request(new_socket):
        # 接收客户端发过来的数据
        recv_data = new_socket.recv(4096)
        # 如果没有收到数据,那么请求无效,关闭套接字,直接退出
        if len(recv_data) == 0:
            new_socket.close()
            return
        # 对接收的字节数据,转换成字符数据
        request_data = recv_data.decode('utf-8')
        # print('浏览器请求的数据:',request_data)
        request_lst = request_data.split(' ',maxsplit=2)
        # 得到请求路径
        request_path = request_lst[1]
        # print('请求路径是:',request_path)
        if request_path == '/': # 如果请求路径为根目录,自动设置为/index.html
            request_path = '/index.html'

        # 根据请求路径,来判断是动态资源还是静态资源
        if request_path.endswith('.html'):
            # 动态资源的请求
            # 动态资源交给web框架来处理,需要把请求参数传给web框架,可能会有多个参数,所以采用字典结构
            params={
                'request_path':request_path,
            }
            # web框架处理动态资源请求之后,返回一个响应
            response = MyFramework.handle_request(params)
            new_socket.send(response)
            new_socket.close()

        else:
            # 静态资源的请求
            # 起始就是根据请求路径读取目录/static中的静态文件数据,响应给客户端
            response_body = None
            response_first_line = None
            try:
                # 读取static目录中对应的文件数据,rb模式:是一种兼容模式,可以打开图片,也可以打开JS文件
                with open('static'+request_path,'rb') as f:
                    response_body = f.read()
                response_first_line = 'HTTP/1.1 200 OK\r\n'
            except Exception as  e:# 浏览器想读取的文件可能不存在
                with open('static/404.html','rb') as f:
                    response_body = f.read() # 响应主体页面内容(字节数据)
                response_first_line = 'HTTP/1.1 404 Not Found\r\n'
            finally:
                # 响应头(字符数据)
                response_header = 'Server: Apache\r\n'
                # 组成响应数据,发送给客户端浏览器
                response = (response_first_line+response_header + '\r\n').encode('utf-8')+response_body
                new_socket.send(response)
                new_socket.close()

    # 启动服务器,并且接收客户端的请求
    def start(self):
        # 循环并且多线程来接收客户端的请求
        while True:
            new_socket,ip_port = self.server_socket.accept()
            # print('客户端的ip和端口',ip_port)
            # 一个客户端请求交给一个线程处理
            sub_thread = threading.Thread(target=self.handle_browser_request,args=(new_socket,))
            sub_thread.setDaemon(True) #设置当前线程为守护线程
            sub_thread.start() # 启动子线程
# web服务器程序的入口
def main():
    web_server = MyHttpWebServer(8080)
    web_server.start()

if __name__ == '__main__':
    main()

2、开发web框架主体程序

  1. 根据请求路径,动态的响应对应的数据
  2. 如果请求路径没有对应的响应数据也需要返回404页面
    MyFramework.py
# 处理动态资源请求的参数
import time

def handle_request(params):
    request_path = params.get('request_path')

    if request_path == '/index.html':# 当前的请求路径有与之对应的动态响应,当前框架值开发了index.html的功能
        response = index()
    elif request_path == '/userinfo.html': # 个人中心的功能,user_info.html
        response = user_info()
    else:
        # 没有动态资源的数据,返回404页面
        response = page_not_found()
    return response
# 当前index函数,专门处理index.html的请求
def index():
    # 需求:在页面中动态
    response_first_line = 'HTTP/1.1 200 OK\r\n'
    with open('template/index.html','r',encoding='utf-8') as f:
        response_body = f.read()
    datas = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
    response_body = response_body.replace('{%datas%}',datas)
    response_header = 'Server: Apache\r\n'
    response = (response_first_line + response_header + '\r\n' + response_body + '\r\n').encode('utf-8')
    return response

# 专门处理userinfo.html的动态请求
def user_info():
    # 需求:在页面中动态
    response_first_line = 'HTTP/1.1 200 OK\r\n'
    with open('template/user_info.html', 'r', encoding='utf-8') as f:
        response_body = f.read()
    datas = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
    response_body = response_body.replace('{%datas%}', datas)
    response_header = 'Server: Apache\r\n'
    response = (response_first_line + response_header + '\r\n' + response_body + '\r\n').encode('utf-8')
    return response

# 处理没有找到对应的动态资源
def page_not_found():
    with open('static/404.html', 'rb') as f:
        response_body = f.read()  # 响应主体页面内容(字节数据)
    response_first_line = 'HTTP/1.1 404 Not Found\r\n'
    response_header = 'Server: Apache\r\n'
    # 组成响应数据,发送给客户端浏览器
    response = (response_first_line + response_header + '\r\n').encode('utf-8') + response_body
    return response

3、使用模板显示响应内容

  1. 自己设计一个模板(index.html),有一些地方采用动态的数据来代替
  2. 需要替代的数据有哪些
    index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>首页电影列表</title>
    <link href="../css/bootstrap.min.css" rel="stylesheet">
    <script src="../js/jquery-1.12.4.min.js"></script>
    <script src="../js/bootstrap.min.js"></script>
</head>
<body>
<div class="navbar navbar-inverse navbar-static-top">
    <div class="container">
        <div class="navbar-header">
            <button class="navbar-toggle" data-toggle="collapse" data-target="#mymenu">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
            </button>
            <a href="#" class="navbar-brand">电影列表</a>
        </div>
        <div class="collapse navbar-collapse" id="mymenu">
            <ul class="nav navbar-nav">
                <li class="active"><a href="">电影信息</a> </li>
                <li><a href="">个人中心</a></li>
            </ul>
        </div>
    </div>
</div>
<div class="container">
    <div class="container-fluid">
        <table class="table table-hover">
            <tr>
                <th>序号</th>
                <th>名称</th>
                <th>导演</th>
                <th>上映时间</th>
                <th>票房</th>
                <th>电影时长</th>
                <th>类型</th>
                <th>备注</th>
                <th>删除电影</th>
            </tr>
            {%datas%}
        </table>
    </div>
</div>
</body>
</html>

user_info.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>个人中心</title>
    <link href="../css/bootstrap.min.css" rel="stylesheet">
    <script src="../js/jquery-1.12.4.min.js"></script>
    <script src="../js/bootstrap.min.js"></script>
</head>
<body>
<div class="navbar navbar-inverse navbar-static-top">
    <div class="container">
        <div class="navbar-header">
            <button class="navbar-toggle" data-toggle="collapse" data-target="#mymenu">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
            </button>
            <a href="#" class="navbar-brand">个人中心</a>
        </div>
        <div class="collapse navbar-collapse" id="mymenu">
            <ul class="nav navbar-nav">
                <li ><a href="">电影信息</a> </li>
                <li class="active"><a href="">个人中心</a></li>
            </ul>
        </div>
    </div>
</div>
<div class="container">
    <div class="container-fluid">
        <table class="table table-hover">
            <tr>
                <th>用户名</th>
                <th>密码</th>
                <th>年龄</th>
                <th>性别</th>
            </tr>
            {%datas%}
        </table>
    </div>
</div>
</body>
</html>

404.html

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
    <meta charset="UTF-8">
<title>404 资源没有发现</title>
</head><body>
<h1>资源没有发现</h1>
</body></html>

4、开发路由的列表功能

  1. 以后开发新的动态资源的功能,只需要增加一个条件判断分支,增加一个专门处理的函数
  2. 路由:就是请求的URL路径和处理函数之间的映射
  3. 路由表
请求路径处理函数
/index.htmlindex函数
/userinfo.htmluser_info函数

注意:用户的动态资源请求,通过遍历路由表找到对应的函数来完成
MyFramework.py

# 处理动态资源请求的参数
import time

def handle_request(params):
    request_path = params.get('request_path')

    for path,func in route_list:
        if path == request_path:
            response = func()
            break
    else:
        response = page_not_found()
    return response
# 当前index函数,专门处理index.html的请求
def index():
    # 需求:在页面中动态
    response_first_line = 'HTTP/1.1 200 OK\r\n'
    with open('template/index.html','r',encoding='utf-8') as f:
        response_body = f.read()
    datas = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
    response_body = response_body.replace('{%datas%}',datas)
    response_header = 'Server: Apache\r\n'
    response = (response_first_line + response_header + '\r\n' + response_body + '\r\n').encode('utf-8')
    return response

# 专门处理userinfo.html的动态请求
def user_info():
    # 需求:在页面中动态
    response_first_line = 'HTTP/1.1 200 OK\r\n'
    with open('template/user_info.html', 'r', encoding='utf-8') as f:
        response_body = f.read()
    datas = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
    response_body = response_body.replace('{%datas%}', datas)
    response_header = 'Server: Apache\r\n'
    response = (response_first_line + response_header + '\r\n' + response_body + '\r\n').encode('utf-8')
    return response

# 处理没有找到对应的动态资源
def page_not_found():
    with open('static/404.html', 'rb') as f:
        response_body = f.read()  # 响应主体页面内容(字节数据)
    response_first_line = 'HTTP/1.1 404 Not Found\r\n'
    response_header = 'Server: Apache\r\n'
    # 组成响应数据,发送给客户端浏览器
    response = (response_first_line + response_header + '\r\n').encode('utf-8') + response_body
    return response

#定义路由表
route_list = {
    ('/index.html',index),
    ('/userinfo.html',user_info)
}

5、采用装饰器的方式添加路由

  1. 采用带参数的路由器
  2. 在任何一个处理函数的基础上添加一个路由的功能
    MyFramework.py
# 处理动态资源请求的参数
import time
from functools import wraps

route_list=[]

# 定义一个带参数的装饰器
def route(request_path): # 参数就是url请求
    def add_route(func):
        # 添加路由到路由表
        route_list.append((request_path,func))
        # print(route_list)
        @wraps(func)
        def invoke(*args,**kwargs):
            # 调用指定的处理函数,并且返回结果
            return func()
        return invoke
    return add_route

def handle_request(params):
    request_path = params.get('request_path')

    for path,func in route_list:
        if path == request_path:
            response = func()
            break
    else:
        response = page_not_found()
    return response
# 当前index函数,专门处理index.html的请求
@route(request_path='/index.html')
def index():
    # 需求:在页面中动态
    response_first_line = 'HTTP/1.1 200 OK\r\n'
    with open('template/index.html','r',encoding='utf-8') as f:
        response_body = f.read()
    datas = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
    response_body = response_body.replace('{%datas%}',datas)
    response_header = 'Server: Apache\r\n'
    response = (response_first_line + response_header + '\r\n' + response_body + '\r\n').encode('utf-8')
    return response

# 专门处理userinfo.html的动态请求
@route(request_path='/userinfo.html')
def user_info():
    # 需求:在页面中动态
    response_first_line = 'HTTP/1.1 200 OK\r\n'
    with open('template/user_info.html', 'r', encoding='utf-8') as f:
        response_body = f.read()
    datas = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
    response_body = response_body.replace('{%datas%}', datas)
    response_header = 'Server: Apache\r\n'
    response = (response_first_line + response_header + '\r\n' + response_body + '\r\n').encode('utf-8')
    return response

# 处理没有找到对应的动态资源
def page_not_found():
    with open('static/404.html', 'rb') as f:
        response_body = f.read()  # 响应主体页面内容(字节数据)
    response_first_line = 'HTTP/1.1 404 Not Found\r\n'
    response_header = 'Server: Apache\r\n'
    # 组成响应数据,发送给客户端浏览器
    response = (response_first_line + response_header + '\r\n').encode('utf-8') + response_body
    return response

6、电影列表页面的开发

  1. 查询数据
  2. 根据查询的数据得到动态的内容
    只需要修改index函数,增加数据库查询,将html页面的数据进行替换即可
    MyFramework.py
import time
from functools import wraps
import pymysql

route_list=[]

# 定义一个带参数的装饰器
def route(request_path): # 参数就是url请求
    def add_route(func):
        # 添加路由到路由表
        route_list.append((request_path,func))
        # print(route_list)
        @wraps(func)
        def invoke(*args,**kwargs):
            # 调用指定的处理函数,并且返回结果
            return func()
        return invoke
    return add_route

def handle_request(params):
    request_path = params.get('request_path')

    for path,func in route_list:
        if path == request_path:
            response = func()
            break
    else:
        response = page_not_found()
    return response
# 当前index函数,专门处理index.html的请求
@route(request_path='/index.html')
def index():
    # 需求:从数据库中取得所有的电影数据,并且动态展示
    # 1. 在mysql中查询数据
    conn = pymysql.connect(host='localhost',port=3306,user='admin',password='admin123',database='mytestdb',charset='utf8')
    cursor = conn.cursor()
    cursor.execute('select * from t_movies')
    result = cursor.fetchall()
    print(result)

    # 把查询的数据转换成动态内容
    datas = ""
    for row in result:
        datas += '''
            <tr>
                <td>%s</td>
                <td>%s</td>
                <td>%s</td>
                <td>%s</td>
                <td>%s 亿人民币</td>
                <td>%s</td>
                <td>%s</td>
                <td>%s</td>
                <td><input type="button" value="删除"/></td>
            </tr>
        ''' %row
    print(datas)
    response_first_line = 'HTTP/1.1 200 OK\r\n'
    with open('template/index.html','r',encoding='utf-8') as f:
        response_body = f.read()
    # datas = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
    response_body = response_body.replace('{%datas%}',datas)
    response_header = 'Server: Apache\r\n'
    response = (response_first_line + response_header + '\r\n' + response_body + '\r\n').encode('utf-8')
    return response

# 专门处理userinfo.html的动态请求
@route(request_path='/userinfo.html')
def user_info():
    # 需求:在页面中动态
    response_first_line = 'HTTP/1.1 200 OK\r\n'
    with open('template/user_info.html', 'r', encoding='utf-8') as f:
        response_body = f.read()
    datas = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
    response_body = response_body.replace('{%datas%}', datas)
    response_header = 'Server: Apache\r\n'
    response = (response_first_line + response_header + '\r\n' + response_body + '\r\n').encode('utf-8')
    return response

# 处理没有找到对应的动态资源
def page_not_found():
    with open('static/404.html', 'rb') as f:
        response_body = f.read()  # 响应主体页面内容(字节数据)
    response_first_line = 'HTTP/1.1 404 Not Found\r\n'
    response_header = 'Server: Apache\r\n'
    # 组成响应数据,发送给客户端浏览器
    response = (response_first_line + response_header + '\r\n').encode('utf-8') + response_body
    return response

3、虚拟环境介绍

虚拟环境,是一个虚拟化,从电脑独立开发出来的环境。通俗的来讲,虚拟环境就借助虚拟机来把一部分内容独立出来,我们把这部分独立出来的东西称作容器。在这个容器中,我们可以只安装我们需要的依赖包,各个容器之间相互隔离,互不影响。

4、为什么使用虚拟环境

  1. 项目部署时,直接导出项目对应的环境中的库就可以了
  2. 同时开发多个项目,各自项目使用的python版本不同,譬如一个是python2,一个是python3,那么就需要来回的切换多个版本
  3. 当同时开发多个项目时,特别是多个项目使用同一个库,多个项目使用一个模块的不同版本,就需要来回的卸载和安装不同的版本,因为同一个python环境中,同名的库只能有一个版本

5、虚拟环境的安装

安装虚拟环境库

pip install virtualenv

6、虚拟环境优化

在使用过程中,通过安装virtualwrapper-win可以更加简便的使用虚拟环境

  1. 安装
pip install virtualenvwrapper-win 
  1. 配置环境变量
    1. 新建系统变量名:WORKON_HOME
    2. 变量值配置为一个指定目录:D:\env
    3. 在盘符中创建相应文件
    4. 保存配置
  2. 在cmd中运行workon或isvirtualenv可查看当前的虚拟环境配置情况
  3. 新建虚拟环境
mkvirtualenv env-name  

注意:可以在cmd中任意路径下执行语句,创建的环境都会保存在配置的环境变量下的路径中
5. 激活虚拟环境

workon env-name
  1. 退出虚拟环境
deactivate
  1. 删除虚拟环境
rmvirtualenv env-name
库只能有一个版本
## 5、虚拟环境的安装
安装虚拟环境库
```shell
pip install virtualenv

6、虚拟环境优化

在使用过程中,通过安装virtualwrapper-win可以更加简便的使用虚拟环境

  1. 安装
pip install virtualenvwrapper-win 
  1. 配置环境变量
    1. 新建系统变量名:WORKON_HOME
    2. 变量值配置为一个指定目录:D:\env
    3. 在盘符中创建相应文件
    4. 保存配置
  2. 在cmd中运行workon或isvirtualenv可查看当前的虚拟环境配置情况
  3. 新建虚拟环境
mkvirtualenv env-name  

注意:可以在cmd中任意路径下执行语句,创建的环境都会保存在配置的环境变量下的路径中
5. 激活虚拟环境

workon env-name
  1. 退出虚拟环境
deactivate
  1. 删除虚拟环境
rmvirtualenv env-name
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值