Python高级 -- 12 mini_frame框架添加路由、路由支持正则、Log日志功能

一、路由


1、mini_frame中实现简单的路由功能


mini_frame.py


# coding=UTF-8
import re

def index():
    with open("./templates/index.html") as f:
        
        content = f.read()

        # 使用正则表达式替换源模版中的数据

        from_mysql_data = "这里以后放的是从数据库中查询出来的数据"
        
        content = re.sub(r"\{%content%\}", from_mysql_data, content)

        return content

def center():
    with open("./templates/center.html") as f:
        
        return f.read()

URL_FUN_DIC = {
        "/index.py":index,
        "/center.py":center
        }


def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html;charset=utf-8')])
    
    file_name = env['PATH_INFO']

    """
        if file_name == "/index.py":
            return index()
        elif file_name == "/center.py":
            return center()
        else:
            return "我爱你中国..."
    """
    func = URL_FUN_DIC[file_name]
    return func()


2、使用装饰器完成mini_frame.py的路由功能


mini_frame.py


# coding=UTF-8
import re


URL_FUN_DIC = dict()


def route(url):
    def set_func(func):
        # 在执行装饰的过程中将参数添加到字典中
        URL_FUN_DIC[url] = func
        def call_func(*args, **kwargs):
            return func(*args, **kwargs)
        return call_func
    return set_func


@route("/index.py")
def index():
    with open("./templates/index.html") as f:
        
        content = f.read()

        # 使用正则表达式替换源模版中的数据

        from_mysql_data = "这里以后放的是从数据库中查询出来的数据"
        
        content = re.sub(r"\{%content%\}", from_mysql_data, content)

        return content
    

@route("/center.py")
def center():
    with open("./templates/center.html") as f:
        
        return f.read()


def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html;charset=utf-8')])
    
    file_name = env['PATH_INFO']

    """
        if file_name == "/index.py":
            return index()
        elif file_name == "/center.py":
            return center()
        else:
            return "我爱你中国..."
    """
    try:
        return URL_FUN_DIC[file_name]()
    except Exception as e:
        return "您访问的页面 %s 不存在" % str(e)
    return func()


二、伪静态、静态和动态


1、静态URL


        静态URL类似 域名/news/2012-5-18/110.html 我们一般称为真静态URL,每个网页有真实的物理路径,也就是真实存在服务器里的。


优点是:


        网站打开速度快,因为它不用进行运算;另外网址结构比较友好,利于记忆。


缺点是:


        最大的缺点是如果是中大型网站,则产生的页面特别多,不好管理。至于有的开发者说占用硬盘空间大,我觉得这个可有忽略不计,占用不了多少空间的,况且目前硬盘空间都比较大。还有的开发者说会伤硬盘,这点也可以忽略不计。


一句话总结:

 

        静态网站对SEO的影响:静态URL对SEO肯定有加分的影响,因为打开速度快,这个是本质。


2、动态URL


        动态URL类似 域名/NewsMore.asp?id=5 或者 域名/DaiKuan.php?id=17,带有?号的URL,我们一般称为动态网址,每个URL只是一个逻辑地址,并不是真实物理存在服务器硬盘里的。


优点是:


        适合中大型网站,修改页面很方便,因为是逻辑地址,所以占用硬盘空间要比纯静态网站小。


缺点是:


        因为要进行运算,所以打开速度稍慢,不过这个可有忽略不计,目前有服务器缓存技术可以解决速度问题。最大的缺点是URL结构稍稍复杂,不利于记忆。


一句话总结:


        动态URL对SEO的影响:目前百度SE已经能够很好的理解动态URL,所以对SEO没有什么减分的影响(特别复杂的URL结构除外)。所以你无论选择动态还是静态其实都无所谓,看你选择的程序和需求了。


3、伪静态URL


        伪静态URL类似 域名/course/74.html 这个URL和真静态URL类似。他是通过伪静态规则把动态URL伪装成静态网址。也是逻辑地址,不存在物理地址。


优点是:


        URL比较友好,利于记忆。非常适合大中型网站,是个折中方案。


缺点是:


        设置麻烦,服务器要支持重写规则,小企业网站或者玩不好的就不要折腾了。另外进行了伪静态网站访问速度并没有变快,因为实质上它会额外的进行运算解释,反正增加了服务器负担,速度反而变慢,不过现在的服务器都很强大,这种影响也可以忽略不计。还有可能会造成动态URL和静态URL都被搜索引擎收录,不过可以用robots禁止掉动态地址。


一句话总结:


        对SEO的影响:和动态URL一样,对SEO没有什么减分影响。


4、让web服务器支持伪静态


(1)、修改web-server.py中捕获的请求后缀名




(2)、修改mini_frame.py框架




三、web服务器动态查询MySQL数据库中的数据并展示


1、准备数据库数据


create database stock_db charset=utf8;

use stock_db;

DROP TABLE IF EXISTS `focus`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `focus` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `note_info` varchar(200) DEFAULT '',
  `info_id` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `info_id` (`info_id`),
  CONSTRAINT `focus_ibfk_1` FOREIGN KEY (`info_id`) REFERENCES `info` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `focus`
--

LOCK TABLES `focus` WRITE;
/*!40000 ALTER TABLE `focus` DISABLE KEYS */;
INSERT INTO `focus` VALUES (2,'你确定要买这个?',36),(3,'利好',37),(9,'',88),(10,'',89),(13,'',1);
/*!40000 ALTER TABLE `focus` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `info`
--

DROP TABLE IF EXISTS `info`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `info` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `code` varchar(6) NOT NULL COMMENT '股票代码',
  `short` varchar(10) NOT NULL COMMENT '股票简称',
  `chg` varchar(10) NOT NULL COMMENT '涨跌幅',
  `turnover` varchar(255) NOT NULL COMMENT '换手率',
  `price` decimal(10,2) NOT NULL COMMENT '最新价',
  `highs` decimal(10,2) NOT NULL COMMENT '前期高点',
  `time` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=95 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `info`
--

LOCK TABLES `info` WRITE;
/*!40000 ALTER TABLE `info` DISABLE KEYS */;
INSERT INTO `info` VALUES 
	(1,'000007','全新好','10.01%','4.40%',16.05,14.60,'2017-07-18'),(2,'000036','华联控股','10.04%','10.80%',11.29,10.26,'2017-07-20'),
	(3,'000039','中集集团','1.35%','1.78%',18.07,18.06,'2017-06-28'),(4,'000050','深天马A','4.38%','4.65%',22.86,22.02,'2017-07-19'),
	(5,'000056','皇庭国际','0.39%','0.65%',12.96,12.91,'2017-07-20'),(6,'000059','华锦股份','3.37%','7.16%',12.26,12.24,'2017-04-11'),
	(7,'000060','中金岭南','1.34%','3.39%',12.08,11.92,'2017-07-20'),(8,'000426','兴业矿业','0.41%','2.17%',9.71,9.67,'2017-07-20'),
	(9,'000488','晨鸣纸业','6.30%','5.50%',16.37,15.59,'2017-07-10'),(10,'000528','柳工','1.84%','3.03%',9.42,9.33,'2017-07-19'),
	(11,'000540','中天金融','0.37%','5.46%',8.11,8.08,'2017-07-20'),(12,'000581','威孚高科','3.49%','3.72%',27.00,26.86,'2017-06-26'),
	(13,'000627','天茂集团','5.81%','12.51%',10.93,10.33,'2017-07-20'),(14,'000683','远兴能源','6.42%','21.27%',3.48,3.29,'2017-07-19'),
	(15,'000703','恒逸石化','0.24%','1.65%',16.92,16.88,'2017-07-20'),(16,'000822','山东海化','6.60%','8.54%',9.05,8.75,'2017-07-06'),
	(17,'000830','鲁西化工','1.38%','4.80%',7.36,7.26,'2017-07-20'),(18,'000878','云南铜业','1.26%','3.23%',14.50,14.47,'2017-07-19'),
	(19,'000905','厦门港务','5.44%','10.85%',15.90,15.60,'2017-04-20'),(20,'000990','诚志股份','0.53%','1.00%',16.99,16.90,'2017-07-20'),
	(21,'002019','亿帆医药','1.19%','2.81%',17.05,16.85,'2017-07-20'),(22,'002078','太阳纸业','2.05%','1.90%',8.45,8.29,'2017-07-19'),
	(23,'002092','中泰化学','7.25%','6.20%',15.53,14.48,'2017-07-20'),(24,'002145','中核钛白','2.43%','7.68%',6.75,6.61,'2017-07-19'),
	(25,'002285','世联行','8.59%','5.66%',9.23,8.50,'2017-07-20'),(26,'002311','海大集团','1.13%','0.24%',18.81,18.63,'2017-07-19'),
	(27,'002460','赣锋锂业','9.41%','9.00%',63.70,58.22,'2017-07-20'),(28,'002466','天齐锂业','3.62%','3.66%',68.44,66.05,'2017-07-20'),
	(29,'002470','金正大','2.30%','0.99%',8.00,7.82,'2017-07-20'),(30,'002496','辉丰股份','3.15%','4.29%',5.24,5.08,'2017-04-10'),
	(31,'002497','雅化集团','0.38%','12.36%',13.10,13.05,'2017-07-20'),(32,'002500','山西证券','0.44%','3.70%',11.49,11.44,'2017-07-20'),
	(33,'002636','金安国纪','2.70%','11.59%',19.80,19.42,'2017-07-19'),(34,'300032','金龙机电','0.66%','0.72%',15.28,15.18,'2017-07-20'),
	(35,'300115','长盈精密','0.60%','0.59%',33.50,33.41,'2017-07-19'),(36,'300268','万福生科','-10.00%','0.27%',31.77,13.57,'2017-04-10'),
	(37,'300280','南通锻压','3.31%','0.66%',32.20,32.00,'2017-04-11'),(38,'300320','海达股份','0.28%','0.82%',18.26,18.21,'2017-07-20'),
	(39,'300408','三环集团','1.69%','0.81%',23.42,23.17,'2017-07-19'),(40,'300477','合纵科技','2.84%','5.12%',22.10,22.00,'2017-07-12'),
	(41,'600020','中原高速','5.46%','4.48%',5.60,5.31,'2017-07-20'),(42,'600033','福建高速','1.01%','1.77%',4.00,3.99,'2017-06-26'),
	(43,'600066','宇通客车','4.15%','1.49%',23.08,23.05,'2017-06-13'),(44,'600067','冠城大通','0.40%','2.97%',7.56,7.53,'2017-07-20'),
	(45,'600110','诺德股份','2.08%','4.26%',16.16,15.83,'2017-07-20'),(46,'600133','东湖高新','9.65%','21.74%',13.64,12.44,'2017-07-20'),
	(47,'600153','建发股份','3.65%','2.03%',13.35,13.21,'2017-07-10'),(48,'600180','瑞茂通','2.20%','1.07%',14.86,14.54,'2017-07-20'),
	(49,'600183','生益科技','6.94%','4.06%',14.94,14.12,'2017-07-19'),(50,'600188','兖州煤业','1.53%','0.99%',14.56,14.43,'2017-07-19'),
	(51,'600191','华资实业','10.03%','11.72%',15.80,14.36,'2017-07-20'),(52,'600210','紫江企业','6.03%','10.90%',6.68,6.30,'2017-07-20'),
	(53,'600212','江泉实业','1.39%','1.78%',10.20,10.15,'2017-07-19'),(54,'600225','*ST松江','4.96%','2.47%',5.71,5.61,'2017-04-13'),
	(55,'600230','沧州大化','5.74%','13.54%',43.26,40.91,'2017-07-20'),(56,'600231','凌钢股份','2.79%','3.77%',3.68,3.60,'2017-07-19'),
	(57,'600291','西水股份','10.02%','9.23%',34.71,31.55,'2017-07-20'),(58,'600295','鄂尔多斯','4.96%','12.62%',16.51,15.73,'2017-07-20'),
	(59,'600303','曙光股份','8.37%','14.53%',11.53,10.64,'2017-07-20'),(60,'600308','华泰股份','1.12%','2.66%',6.30,6.26,'2017-07-19'),
	(61,'600309','万华化学','0.03%','1.78%',31.81,31.80,'2017-07-20'),(62,'600352','浙江龙盛','0.39%','1.85%',10.32,10.28,'2017-07-20'),
	(63,'600354','敦煌种业','7.89%','18.74%',9.44,8.75,'2017-07-20'),(64,'600408','安泰集团','1.98%','3.38%',4.13,4.12,'2017-04-13'),
	(65,'600409','三友化工','0.62%','3.78%',11.36,11.29,'2017-07-20'),(66,'600499','科达洁能','0.46%','3.94%',8.84,8.80,'2017-07-20'),
	(67,'600508','上海能源','3.26%','2.99%',13.32,13.01,'2017-07-19'),(68,'600563','法拉电子','0.32%','1.36%',53.67,53.50,'2017-07-20'),
	(69,'600567','山鹰纸业','0.76%','2.85%',3.98,3.96,'2017-07-19'),(70,'600585','海螺水泥','0.45%','0.61%',24.51,24.44,'2017-07-19'),
	(71,'600668','尖峰集团','4.35%','6.43%',18.70,18.36,'2017-04-13'),(72,'600688','上海石化','2.72%','0.91%',6.80,6.74,'2017-06-01'),
	(73,'600729','重庆百货','5.70%','3.34%',27.45,27.13,'2017-06-29'),(74,'600739','辽宁成大','3.30%','3.50%',19.74,19.11,'2017-07-20'),
	(75,'600779','水井坊','3.85%','2.77%',29.39,28.30,'2017-07-20'),(76,'600781','辅仁药业','8.61%','4.16%',23.46,21.89,'2017-05-02'),
	(77,'600801','华新水泥','4.00%','10.15%',12.99,12.49,'2017-07-20'),(78,'600846','同济科技','2.06%','17.41%',9.39,9.26,'2017-04-13'),
	(79,'600884','杉杉股份','1.08%','3.53%',20.67,20.45,'2017-07-20'),(80,'600966','博汇纸业','2.89%','5.54%',6.41,6.28,'2017-07-19'),
	(81,'600971','恒源煤电','2.36%','8.81%',12.16,11.88,'2017-07-20'),(82,'601012','隆基股份','0.76%','1.30%',19.93,19.78,'2017-07-20'),
	(83,'601100','恒立液压','4.78%','0.92%',19.31,18.97,'2017-07-13'),(84,'601101','昊华能源','4.03%','6.06%',11.10,10.80,'2017-07-19'),
	(85,'601216','君正集团','2.16%','2.26%',5.20,5.10,'2017-04-17'),(86,'601666','平煤股份','2.81%','6.14%',6.96,6.77,'2017-07-20'),
	(87,'601668','中国建筑','2.39%','1.42%',10.70,10.45,'2017-07-20'),(88,'601678','滨化股份','0.13%','2.47%',7.92,7.91,'2017-07-20'),
	(89,'601918','新集能源','1.23%','3.11%',4.93,4.92,'2017-07-19'),(90,'603167','渤海轮渡','2.77%','3.34%',11.87,11.61,'2017-04-13'),
	(91,'603369','今世缘','3.34%','2.13%',14.24,13.78,'2017-07-20'),(92,'603589','口子窖','3.99%','1.84%',39.37,39.04,'2017-06-26'),
	(93,'603799','华友钴业','2.38%','7.19%',67.46,65.89,'2017-07-20'),(94,'603993','洛阳钼业','2.94%','2.50%',7.36,7.16,'2017-07-19');


2、修改mini_frame.py内容


# coding=UTF-8
import re
from pymysql import connect


URL_FUN_DIC = dict()


def route(url):
    def set_func(func):
        # 在执行装饰的过程中将参数添加到字典中
        URL_FUN_DIC[url] = func
        def call_func(*args, **kwargs):
            return func(*args, **kwargs)
        return call_func
    return set_func


@route("/index.html")
def index():
    with open("./templates/index.html") as f:
        
        content = f.read()

        # 从数据库中将数据查询出来
        conn = connect(host='localhost', port=3306, user='root', password='mysql', database='stock_db',  
                       charset='utf8') 
        # 获得cursor对象
        cs = conn.cursor()
        cs.execute("select * from info;")

        stock_info_list = cs.fetchall()
        cs.close()
        conn.close()

        #按照页面要求的格式组装数据
        tr_template = """<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="添加" id="toAdd" name="toAdd" systemidvaule="%s">
                        </td>
                        </tr>
                    """

        # 使用正则表达式替换源模版中的数据

        from_mysql_data = ""

        for data in stock_info_list:
            from_mysql_data += tr_template %(data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7],data[1])

        # 使用正则表达式替换源模版中的数据

        # from_mysql_data = "这里以后放的是从数据库中查询出来的数据"
        
        content = re.sub(r"\{%content%\}", from_mysql_data, content)

        return content
    

@route("/center.html")
def center():
    with open("./templates/center.html") as f:
        
        content = f.read()

        # 从数据库中将数据查询出来
        conn = connect(host='localhost', port=3306, user='root', password='mysql', database='stock_db',  
                       charset='utf8') 
        # 获得cursor对象
        cs = conn.cursor()
        cs.execute("select i.code,i.short,i.chg,i.turnover,i.price,i.highs,f.note_info from info as i inner join focus as f on i.id=f.info_id;")

        stock_info_list = cs.fetchall()
        cs.close()
        conn.close()

        #按照页面要求的格式组装数据
        tr_template = """<tr>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>
                                <a type="button" class="btn btn-default btn-xs" href="/update/%s.html"> <span class="glyphicon glyphicon-star" aria-hidden="true"></span> 修改 </a>
                            </td>
                            <td>
                                <input type="button" value="删除" id="toDel" name="toDel" systemidvaule="%s">
                            </td>
                        </tr>
                    """

        # 使用正则表达式替换源模版中的数据

        from_mysql_data = ""

        for data in stock_info_list:
            from_mysql_data += tr_template %(data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[0],data[0])

        # 使用正则表达式替换源模版中的数据

        # from_mysql_data = "这里以后放的是从数据库中查询出来的数据"
        
        content = re.sub(r"\{%content%\}", from_mysql_data, content)

        return content


def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html;charset=utf-8')])
    
    file_name = env['PATH_INFO']

    """
        if file_name == "/index.py":
            return index()
        elif file_name == "/center.py":
            return center()
        else:
            return "我爱你中国..."
    """
    try:
        return URL_FUN_DIC[file_name]()
    except Exception as e:
        return "您访问的页面 %s 不存在" % str(e)
    return func()


四、mini_frame.py框架路由支持正则


1、修改mini_frame.py代码




@route(r"/add/\d+\.html")
def add_func():
    return "ADD 0K...."


def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html;charset=utf-8')])
    
    file_name = env['PATH_INFO']

    """
        if file_name == "/index.py":
            return index()
        elif file_name == "/center.py":
            return center()
        else:
            return "我爱你中国..."
    """
    try:
        # return URL_FUN_DIC[file_name]()
        """
            使用正则表达式当作装饰器的参数之后,字典中的数据如下:

            {
                "/index.html":index,
                "/center.html"center,
                r"/add/\d+\.html":add_func
            }
            
            使用item()方法进行遍历,取出每一个url和func

        """
        for url, func in URL_FUN_DIC.items():
            ret = re.match(url, file_name)
            if ret:
                return func()
        else:
            return "请求的页面 %s 不存在" % file_name

    except Exception as e:
        return "您访问的页面 %s 不存在" % str(e)
    return func()


2、实现添加关注功能


# coding=UTF-8
import re
from pymysql import connect


URL_FUN_DIC = dict()


def route(url):
    def set_func(func):
        # 在执行装饰的过程中将参数添加到字典中
        URL_FUN_DIC[url] = func
        def call_func(*args, **kwargs):
            return func(*args, **kwargs)
        return call_func
    return set_func


@route("/index.html")
def index(ret):
    with open("./templates/index.html") as f:
        
        content = f.read()

        # 从数据库中将数据查询出来
        conn = connect(host='localhost', port=3306, user='root', password='mysql', database='stock_db',  
                       charset='utf8') 
        # 获得cursor对象
        cs = conn.cursor()
        cs.execute("select * from info;")

        stock_info_list = cs.fetchall()
        cs.close()
        conn.close()

        #按照页面要求的格式组装数据
        tr_template = """<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="添加" id="toAdd" name="toAdd" systemidvaule="%s">
                        </td>
                        </tr>
                    """

        # 使用正则表达式替换源模版中的数据

        from_mysql_data = ""

        for data in stock_info_list:
            from_mysql_data += tr_template %(data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7],data[1])

        # 使用正则表达式替换源模版中的数据

        # from_mysql_data = "这里以后放的是从数据库中查询出来的数据"
        
        content = re.sub(r"\{%content%\}", from_mysql_data, content)

        return content
    

@route("/center.html")
def center(ret):
    with open("./templates/center.html") as f:
        
        content = f.read()

        # 从数据库中将数据查询出来
        conn = connect(host='localhost', port=3306, user='root', password='mysql', database='stock_db',  
                       charset='utf8') 
        # 获得cursor对象
        cs = conn.cursor()
        cs.execute("select i.code,i.short,i.chg,i.turnover,i.price,i.highs,f.note_info from info as i inner join focus as f on i.id=f.info_id;")

        stock_info_list = cs.fetchall()
        cs.close()
        conn.close()

        #按照页面要求的格式组装数据
        tr_template = """<tr>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>
                                <a type="button" class="btn btn-default btn-xs" href="/update/%s.html"> <span class="glyphicon glyphicon-star" aria-hidden="true"></span> 修改 </a>
                            </td>
                            <td>
                                <input type="button" value="删除" id="toDel" name="toDel" systemidvaule="%s">
                            </td>
                        </tr>
                    """

        # 使用正则表达式替换源模版中的数据

        from_mysql_data = ""

        for data in stock_info_list:
            from_mysql_data += tr_template %(data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[0],data[0])

        # 使用正则表达式替换源模版中的数据

        # from_mysql_data = "这里以后放的是从数据库中查询出来的数据"
        
        content = re.sub(r"\{%content%\}", from_mysql_data, content)

        return content


@route(r"/add/(\d+)\.html")
def add_func(ret):
    # 获取第一个分组(股票的code)
    stock_code = ret.group(1)

    # 判断当前股票是否存在
    conn = connect(host='localhost', port=3306, user='root', password='mysql', database='stock_db', charset='utf8')
    # 获取游标
    cs = conn.cursor()
    sql = """select * from info where code = %s"""
    cs.execute(sql, (stock_code,))
    # 如果没有当前代码,提示并return
    if not cs.fetchone():
        cs.close()
        conn.close()
        return "没有这只股票,请重试"

    # 判断当前选中的股票是否已经关注过
    sql = """select * from info as i inner join focus as f on i.id=f.info_id where i.code = %s"""
    cs.execute(sql, stock_code)
    # 如果已经关注了当前代码,提示并return
    if cs.fetchone():
        cs.close()
        conn.close()
        return "您已经关注过这只股票,请勿重复关注"

    # 可以开始关注操作,添加关注
    sql = """insert into focus(info_id) select id from info where code=%s"""
    cs.execute(sql, stock_code)
    conn.commit()
    cs.close()
    conn.close()
    
    return "关注 成功 .... "


def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html;charset=utf-8')])
    
    file_name = env['PATH_INFO']

    """
        if file_name == "/index.py":
            return index()
        elif file_name == "/center.py":
            return center()
        else:
            return "我爱你中国..."
    """
    try:
        # return URL_FUN_DIC[file_name]()
        """
            使用正则表达式当作装饰器的参数之后,字典中的数据如下:

            {
                "/index.html":index,
                "/center.html"center,
                r"/add/\d+\.html":add_func
            }
            
            使用item()方法进行遍历,取出每一个url和func

        """
        for url, func in URL_FUN_DIC.items():
            ret = re.match(url, file_name)
            if ret:
                return func(ret)
        else:
            return "请求的页面 %s 不存在" % file_name

    except Exception as e:
        return "您访问的页面 %s 不存在" % str(e)
    return func()


3、实现取消关注的功能




@route(r"/del/(\d+)\.html")
def add_func(ret):
    # 获取第一个分组(股票的code)
    stock_code = ret.group(1)

    # 判断当前股票是否存在
    conn = connect(host='localhost', port=3306, user='root', password='mysql', database='stock_db', charset='utf8')
    # 获取游标
    cs = conn.cursor()
    sql = """select * from info where code = %s"""
    cs.execute(sql, (stock_code,))
    # 如果没有当前代码,提示并return
    if not cs.fetchone():
        cs.close()
        conn.close()
        return "没有这只股票,请重试"

    # 判断当前选中的股票是否已经关注过
    sql = """select * from info as i inner join focus as f on i.id=f.info_id where i.code = %s"""
    cs.execute(sql, stock_code)
    # 如果没有关注当前代码,提示并return
    if not cs.fetchone():
        cs.close()
        conn.close()
        return "您没有关注过这只股票,取消失败"

    # 可以开始取消关注操作,删除关注
    sql = """delete from focus where info_id = (select id from info where code=%s)"""
    cs.execute(sql, stock_code)
    conn.commit()
    cs.close()
    conn.close()
    
    return "取消关注 成功 .... "


4、实现更新股票备注信息的功能




@route(r"/update/(\d+)\.html")
def to_update_view(ret):
    """跳转到修改数据的页面"""
    # 获取股票code
    stock_code = ret.group(1)
    
    # 打开模版页面
    with open("./templates/update.html") as f:
        content = f.read()

    # 根据股票代码查询相关数据
    conn = connect(host='localhost', port=3306, user='root', password='mysql', database='stock_db', charset='utf8')
    cs = conn.cursor()
    sql = """select f.note_info from focus as f inner join info as i on i.id=f.info_id where i.code=%s;"""
    cs.execute(sql, stock_code)
    stock_infos = cs.fetchone()
    note_info = stock_infos[0]  # 获取当前股票的备注信息,用于页面回显
    cs.close()
    conn.close()

    # 替换html页面中的数据
    content = re.sub(r"\{%note_info%\}", note_info, content)
    content = re.sub(r"\{%code%\}", stock_code, content)
    return content


@route(r"/update/(\d+)/(.*)\.html")
def update_stock(ret):
    """修改股票信息"""
    stock_code = ret.group(1)
    comment = ret.group(2)

    conn = connect(host='localhost', port=3306, user='root', password='mysql', database='stock_db', charset='utf8')
    cs = conn.cursor()
    sql = """update focus set note_info=%s where info_id = (select id from info where code = %s)"""
    cs.execute(sql, (comment, stock_code))
    conn.commit()
    cs.close()
    conn.close()

    return "修改成功..."


5、url中有输入非字母时的URL解码


(1)、抛出问题


        当修改的备注信息中有特殊字符或者中文的时候,出现一下情况



解决方案:使用python中的 urllib.parse 模块进行编、解码


(2)、导入urllib.parse模块


import urllib.parse


(3)、修改保存备注信息的方法


# 数据使用URL编码
urllib.parse,quote(字符串)

# 将URL编码方式的字符串进行解码
urllib.parse.unquote(url编码方式的字符串)




五、Log日志


1、日志级别


日志一共分成5个等级,从到高分别是:DEBUG    INFO    WARNING    ERROR    CRITICAL


说明:


        DEBUG:详细的信息,通常只出现在诊断问题上


        INFO:确认一切按预期运行


        WARNING:一个迹象表明,一些意想不到的事情发生了,或表明一些问题在不久的将来(例如。磁盘空间低”)。这个软件还能按预期工作。


        ERROR:更严重的问题,软件没能执行一些功能


        CRITICAL:一个严重的错误,这表明程序本身可能无法继续运行


这5个等级,也分别对应5种打日志的方法: debug 、info 、warning 、error 、critical。默认的是WARNING,当在WARNING或之上时才被跟踪。


2、日志输出


有两种方式记录跟踪,一种输出控制台,另一种是记录到文件中,如日志文件。


(1)、将日志输出到控制台


# 导入log日志模块
import logging

"""
    设置默认日志等级,格式化要输出的内容
"""
logging.basicConfig(level=logging.WARNING,
                    format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')

# 开始使用log功能
logging.info('这是 loggging info message')
logging.debug('这是 loggging debug message')
logging.warning('这是 loggging a warning message')
logging.error('这是 an loggging error message')
logging.critical('这是 loggging critical message')

"""
    输出结果:
        2018-03-25 19:51:38,525 - 模拟京东查询.py[line:9] - WARNING: 这是 loggging a warning message
        2018-03-25 19:51:38,526 - 模拟京东查询.py[line:10] - ERROR: 这是 an loggging error message
        2018-03-25 19:51:38,527 - 模拟京东查询.py[line:11] - CRITICAL: 这是 loggging critical message
        
    只有是WARNING以上的日志等级才会输出,因为设置了默认等级为 WARNING
"""


说明:


        通过logging.basicConfig函数对日志的输出格式及方式做相关配置,上面代码设置日志的输出等级是WARNING级别,意思是WARNING级别以上的日志才会输出。另外还制定了日志输出的格式。


        注意,只要用过一次log功能再次设置格式时将失效,实际开发中格式肯定不会经常变化,所以刚开始时需要设定好格式。


(2)、将日志输出到日志文件


将日志输出到文件,只需要在logging.basicConfig函数中设置好输出文件的文件名和写文件的模式。


import logging  

logging.basicConfig(level=logging.WARNING,  
                    filename='./log.txt',  # 设置文件的名称以及位置
                    filemode='w',  # 设置打开日志文件的方式
                    format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')  
# use logging  
logging.info('这是 loggging info message')  
logging.debug('这是 loggging debug message')  
logging.warning('这是 loggging a warning message')  
logging.error('这是 an loggging error message')  
logging.critical('这是 loggging critical message')


(3)、将日志输出到控制台和日志文件


import logging  

# 第一步,创建一个logger
logger = logging.getLogger()
logger.setLevel(logging.INFO)  # 设置日志的等级等级总开关

# 第二步,创建一个handler对象,用于写入日志文件
logfile = './log.txt'
fh = logging.FileHandler(logfile, mode='a')  # open的打开模式这里可以进行参考
fh.setLevel(logging.DEBUG)  # 输出到file的log等级的开关

# 第三步,再创建一个handler,用于输出到控制台
ch = logging.StreamHandler()
ch.setLevel(logging.WARNING)   # 输出到console的log等级的开关

# 第四步,定义日志信息的输出格式
formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
fh.setFormatter(formatter)  # 给文件中的日志信息设置输出格式
ch.setFormatter(formatter)  # 给控制台的日志信息设置输出格式

# 第五步,将logger添加到handler里面
logger.addHandler(fh)
logger.addHandler(ch)

# 日志
logger.debug('这是 logger debug message')
logger.info('这是 logger info message')
logger.warning('这是 logger warning message')
logger.error('这是 logger error message')
logger.critical('这是 logger critical message')


3、日志格式说明


logging.basicConfig函数中,可以指定日志的输出格式format,这个参数可以输出很多有用的信息,如下:


        %(levelno)s: 打印日志级别的数值


       %(levelname)s: 打印日志级别名称


       %(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]


       %(filename)s: 打印当前执行程序名


       %(funcName)s: 打印日志的当前函数


       %(lineno)d: 打印日志的当前行号


       %(asctime)s: 打印日志的时间


       %(thread)d: 打印线程ID


       %(threadName)s: 打印线程名称


       %(process)d: 打印进程ID


       %(message)s: 打印日志信息

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值