你好呀~欢迎关注微信公众号:python入门到放弃

web服务器进阶

Python基础 admin 574浏览

web服务器进阶

通过上面的学习,我们发现我们的web服务器没有彻底解耦 1、实现自己指定端口运行我们的web服务器 如果我们的web服务器端口被占用,那么我们的web服务器直接挂掉。 怎么实现?我们可以在执行的时候指定一个端口。 复习: 创建一个Demo.py 写上: import sys print(sys.argv) 我们在黑窗口运行一个python文件的时候,执行命令: python Demo 123 456 会输出:['Demo.py', '123', '456'] 可见,我们是可以给一个程序传递参数的。我们用这个功能,来给我们的web服务器指定端口和框架。 2、利用1中的例子,再给一个框架名,让他直接传一个框架进入。 我们希望运行 python web服务器 7891 Demo:application 来实现调用Demo框架的application方法。 3、写一个配置文件,将web服务器中的寻找文件的路径写进去。

解决上面三个问题才是真的解耦。 思路已经提供给大家,并且看基础是能够写出来的。 接下来我们利用装饰器完成路由功能。对装饰器不懂的可以看看这篇文章:python基础三

# 什么是路由功能?
# 就是请求的url,我们上次通过if判断来写的,很恶心,用另一种方法些
# 我们将Demo框架写成这样(不用再修改web服务器了):
URL_FUNC_DICT = dict()
def url_func(url):
    def set_fun(func):
        URL_FUNC_DICT[url] = func
        def call_func(*args,**kwargs):
            return func(*args,**kwargs)
        return call_func
    return set_fun

@url_func('/login.py')
def login():
    # 这里也可以读取文件
    return '<h1>登录的页面</h1>'

@url_func('/create.py')
def create():
    return '<h1>注册的页面</h1>'

def application(evairon,start_response):
    # 第一个参数返回状态码,第二个以键值的方式返回你想添加的head部分
    start_response('200 ok',[('Content-Type','text/html;charset=utf-8')])
    # 返回给网页的内容
    try:
        file_name = evairon['path_info']
        fun = URL_FUNC_DICT[file_name]
        return fun()
    except Exception as e:
        return '未找到文件'

伪静态实现

在前面说过我们只是暂时任务请求以.py结尾的url为动态的。实际上不是这样。 上面才是动态网页? 静态的:域名/index.html 动态的:域名/index.aspx?page=xxx&xxxxx=xxxx, 伪静态:域名/cour/index.html web服务器实现伪静态: 修改web服务器中判断是.py结尾为以.html结尾,其它不用管。 修改Demo框架中装饰器的参数为.html结尾。

给Demo框架连接数据库并显示到页面

# 数据库运用我们mysql教程中给大家演示的那个student数据库。
# 对于python操作数据库没了解的请去看mysql数据库系列文章。
# 我们在Demo新创建一个mysqldata方法,并且加上装饰器
@url_func('/mysqldata.html')
def mysqldata():
    conn = connect(host='localhost',port=3306,user='root',password='123456',database='student',charset='utf8')
    cursor = conn.cursor()
    cursor.execute("select * from studentinfo")
    text = cursor.fetchall()
    cursor.close()
    conn.close()
    return str(text)
在浏览器中输入127.0.0.1:端口号/mysqldata.html即可看到内容。
查出来是这样的:((1, '张三', 1, '男', 23, '武汉', b'\x00'), (2, '小花', 2, '女', 20, '长沙', b'\x00'), (3, '李四', 3, '男', 21, '上海', b'\x00'), (4, '小猫', 1, '女', 18, '北京', b'\x00'), (6, '小狗', 3, '女', 25, '成都', b'\x00'), (7, '赵六', 1, '男', 26, '天津', b'\x00'))
看着很恶心,给个格式。修改mysqldata方法:
这里会用到html的知识点,希望自己补充。修改成:
@url_func('/mysqldata.html')
def mysqldata():
    conn = connect(host='localhost',port=3306,user='root',password='123456',database='student',charset='utf8')
    cursor = conn.cursor()
    cursor.execute("select * from studentinfo")
    text = cursor.fetchall()
    cursor.close()
    conn.close()
    html = "<table border='1' width = '400px' cellspacing='0' cellpadding='0'>"
    tr_html = '''
                <tr>
                <td>%s</td>
                <td>%s</td>
                <td>%s</td>
                <td>%s</td>
                <td>%s</td>
                <td>%s</td>
                <td>%s</td>
                </tr>
     '''
    for item in text:
        html += tr_html %(item[0],item[1],item[2],item[3],item[4],item[5],item[6])
    html +="</table>"
    return str(html)
# 这样就好看多了。当然你想显示什么就数据库查什么就好了。

完善Demo框架

'''
1、给路由添加正则
现在我们的url返回的都是固定的,比如我们想要删除一个数据,请求的url为/delete/xxx.html
我们需要传递一个xxx,表示id,这个id是不确定的,所以我们需要正则匹配,只要是这种格式,我们都执行
delete方法。修改如下:
修改application方法:
'''
def application(evairon,start_response):
    # 第一个参数返回状态码,第二个以键值的方式返回你想添加的head部分
    start_response('200 ok',[('Content-Type','text/html;charset=utf-8')])
    # 返回给网页的内容
    try:
        file_name = evairon['path_info']
        for url,func in URL_FUNC_DICT.items():
            # 匹配是否有这个函数,有返回回去
            ret = re.match(url,file_name)
            if ret:
                return func(ret)
    except Exception as e:
        return '未找到文件 %s'%e
# 添加delete方法,并匹配所有url为/delete/xxx.html格式的都执行该方法。
@url_func(r'/delete/(\d+)\.html')
def delete(ret):
    return '删除方法。ok'
# 由于给所有函数传递了一个url,所以需要给上面的函数都添加一个参数。

# 执行:成功返回删除方法。ok,那我们继续完善删除方法。
@url_func(r'/delete/(\d+)\.html')
def delete(ret):
    # 获取id值
    id = ret.group(1)
    # 执行sql删除
    conn = connect(host='localhost',port=3306,user='root',password='123456',database='student',charset='utf8')
    cursor = conn.cursor()
    count = cursor.execute("delete from studentinfo where studentid = %s",(id,))
    if count:
        conn.commit()
        cursor.close()
        conn.close()
        return '删除成功。ok!!'
    else:
        return '删除失败!'
'''
其他修改啊,添加,只是sql语句不同,都大同小异。
不过在修改的时候要修改正则,传给数据的还要有修改值没有了解post请求就换个正则匹配
比如127.0.0.1/修改方法/要修改的id/要修改的内容.html,用正则匹配出id和要修改的内容就可以了。
但是有个问题,当我们传递的内容或者汉子的时候会出现乱码,因为是通过url传递的,中途会有个url编码的过程,
'''
# 我们需要解码:
# 1、需要导入模块
import urllib
# 解码:urllib.parse.unquote()
# 编码:urllib.parse.quote()

添加日志模块

不会日志模块需要看基础:python基础之常用模块(二) 导入日志模块:import logging 修改application方法:

def application(evairon,start_response):
    # 第一个参数返回状态码,第二个以键值的方式返回你想添加的head部分
    start_response('200 ok',[('Content-Type','text/html;charset=utf-8')])
    file_name = evairon['path_info']
    # 写入日志
    logging.basicConfig(level=logging.INFO,
                        filename = './log.txt',
                        filemode = 'a',
                        format = '%(asctime)s - %(filename)s[line:%(lineno)d]-%(levelname)s:%(message)s'
    )
    logging.info('访问了%s'%file_name)
    # 返回给网页的内容
    try:
        for url,func in URL_FUNC_DICT.items():
            # 匹配是否有这个函数,有返回回去
            ret = re.match(url,file_name)
            if ret:
                return func(ret)
    except Exception as e:
        logging.WARNING('找不到文件')
        return '未找到文件 %s'%e

后台回复:完整web服务器,获取源代码。

转载请注明: 十三 » web服务器进阶

喜欢 (0) or 分享 ( 0)