广告
返回顶部
首页 > 资讯 > 后端开发 > Python >python中bottle使用实例代码
  • 679
分享到

python中bottle使用实例代码

pythonbottle使用pythonbottle 2022-06-02 23:06:15 679人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

模仿学习同事的代码来写的,主要是搞懂python中如何来组织包,如何调用包,如何读取配置文件,连接数据库,设置路由,路由分组。(注:使用的是python3.6) 整体目录设计如下: 根据调用层级从上往下来说: 首先

模仿学习同事的代码来写的,主要是搞懂python中如何来组织包,如何调用包,如何读取配置文件,连接数据库,设置路由,路由分组。(注:使用的是python3.6)

整体目录设计如下:

根据调用层级从上往下来说:

首先项目根目录下的main.py是整个程序的入口,主要作用启动Http服务器,调用分组路由。

main.py


import bottle
from confg.conf import CONF
from api.user import User
 
db_url = CONF.db.url
 
default_app = bottle.default_app()
 
#相当于分组路由
default_app.mount("/user", User(db_url, "").app)
 
app = default_app
 
if __name__ == '__main__':
    bottle.run(app=app,
               host="localhost",
               port="8000")

接着是controller层,就是api目录。api目录包括service文件夹和api下的文件。(注:一般来说controller层,service层是同级的,本项目其实api下的非service文件都是属于controller层,所以还是同一层的,因为要遵守调用顺序,不然可能会发生循环调用)。

/api/user.py文件


import logging
 
from bottle import request
#db数据库引擎
from common.base import DB
#调用service层
from api.service.user import UserService
 
logger = logging.getLogger("arview")
 
 
class User(DB, UserService):
 
    def __init__(self, *args, **kwargs):
        print(">>> User init begin")
        logging.debug('>>> User init begin')
        super(User, self).__init__(*args, **kwargs)
        self.dispatch()
        logger.debug('>>> User init end')
 
    def create(self, db=None):
        create_body = request.JSON
        create_data = self.create_user(create_body, db)
        return create_data
 
    def delete(self, db=None):
        delete_body = request.json
        delete_data = self.delete_user(delete_body, db)
        return delete_data
 
    def list(self, db=None):
 
        list_data = self.list_user(db)
        return list_data
    #相当于分组路由
    def dispatch(self):
        self.app.route('/listUser', method='post')(self.list)
        self.app.route('/createUser', method='post')(self.create)
        self.app.route('/deleteUser', method='post')(self.delete)

/service/user.py


import time
#model层
from db.models.user import UserModel
 
 
class UserService(object):
    def list_user(self, db):
        user_info_list = db.query(UserModel).all()
        for item in user_info_list:
            print(item.username)
        return user_info_list
 
    def create_user(self, create_body, db):
        user_model = UserModel(
            username=create_body.get("username"),
            passWord=create_body.get("password"),
            role=create_body.get("role"),
            create_time=time.time()
        )
        db.add(user_model)
        db.commit()
        return "success"
 
    def delete_user(self, delete_body, db):
        db.query(UserModel).filter(UserModel.id == (delete_body["id"])).delete()
        db.commit()
        return delete_body

然后是dao层也就是数据库操作层(但是明显虽然有dao层但是数据库操作的逻辑已经在service层里了)

最后是读取配置文件和创建数据库引擎。

读取配置文件使用的包是oslo_config。

conf.py


# coding:utf8
# from __future__ import print_function
from oslo_config import cfg
 
DEFAULT_ARVIEW_DB_NAME = 'ginblog'
DEFAULT_ARVIEW_DB_USER = 'root'
DEFAULT_ARVIEW_DB_USER_PASSWORD = '33DeMysql'
DEFAULT_ARVIEW_DB_HOST = '81.68.179.136'
DEFAULT_ARVIEW_DB_PORT = 3306
DEFAULT_ARVIEW_DB_URL_TEMPLATE = 'mysql+mysqlconnector://{}:{}@' \
                                 '{}:{}/{}?charset=utf8'
DEFAULT_ARVIEW_DB_URL = DEFAULT_ARVIEW_DB_URL_TEMPLATE.fORMat(
    DEFAULT_ARVIEW_DB_USER,
    DEFAULT_ARVIEW_DB_USER_PASSWORD,
    DEFAULT_ARVIEW_DB_HOST,
    DEFAULT_ARVIEW_DB_PORT,
    DEFAULT_ARVIEW_DB_NAME)
 
# 声明参数选项
opt_group = cfg.OptGroup('keystone_authtoken')
mysql_opt_group = cfg.OptGroup('db')
 
auth_opts = [
    cfg.StrOpt('memcached_servers',
               default='localhost:11211',
               choices=("localhost:11211", "0.0.0.0:11211"),
               help=('localhost local', '0.0.0.0 So listen')
               ),
 
    cfg.StrOpt('signing_dir',
               default='/var/cache/cinder',
               choices=("/var/cache/cinder", "/var/cache/cinder"),
               ),
]
 
# mysql
mysql_opts = [
    cfg.StrOpt('url', default=DEFAULT_ARVIEW_DB_URL),
    cfg.StrOpt('Db', default='3mysql'),
    cfg.StrOpt('DbHost', default='381.68.179.136'),
    cfg.StrOpt('DbPort', default='33306'),
    cfg.StrOpt('DbUser', default='3DbUser'),
    cfg.StrOpt('DbPassWord', default='3DbPassWord'),
    cfg.StrOpt('DbName', default='3DbName'),
    cfg.BoolOpt('create', default=False),
    cfg.BoolOpt('commit', default=True),
    cfg.BoolOpt('echo', default=True, help='是否显示回显'),
    cfg.BoolOpt('echo_pool', default=False, help='数据库连接池是否记录 checkouts/checkins操作'),
    cfg.IntOpt('pool_size', default=1000, help='数据库连接池中保持打开的连接数量'),
    cfg.IntOpt('pool_recycle', default=600, help='数据库连接池在连接被创建多久(单位秒)以后回收连接')
]
 
token_opts = [
    cfg.StrOpt('project_domain_name'),
    cfg.StrOpt('project_name'),
]
 
CINDER_OPTS = (auth_opts +
               token_opts)
MYSQLCINDER_OPTS = (mysql_opts)
 
# 注册参数选项
CONF = cfg.CONF
# 注册组
CONF.reGISter_group(opt_group)
CONF.register_group(mysql_opt_group)
 
# 将各个选项注册进组里
CONF.register_opts(CINDER_OPTS, group=opt_group)
CONF.register_opts(MYSQLCINDER_OPTS, group=mysql_opt_group)
 
if __name__ == "__main__":
    # 要读取哪个配置文件
    CONF(default_config_files=['cinder.conf'])
    print('mysql Db配置组为%s' % (CONF.db.Db))
    print('mysql DbHost%s' % (CONF.db.DbHost))
    print('mysql DbPort配置组为%s' % (CONF.db.DbPort))
    print('mysql DbUser%s' % (CONF.db.DbUser))

配置文件cinder.conf


[db]
Db = mysql
DbHost = 81.68.179.136
DbPort = 3306
DbUser = root
DbPassWord = 33demysql
DbName = ginblog
create = false
commit = true
echo = false
echo_pool = false
pool_size = 1000
pool_recycle =600

它的使用方法是,先声明参数选项就是(相当于声明组)

mysql_opt_group = cfg.OptGroup('db'),

然后声明组内的选项,


mysql_opts = [
    cfg.StrOpt('url', default=DEFAULT_ARVIEW_DB_URL),
    cfg.StrOpt('Db', default='3mysql'),
    cfg.StrOpt('DbHost', default='381.68.179.136'),
    cfg.StrOpt('DbPort', default='33306'),
    cfg.StrOpt('DbUser', default='3DbUser'),
    cfg.StrOpt('DbPassWord', default='3DbPassWord'),
    cfg.StrOpt('DbName', default='3DbName'),
    cfg.BoolOpt('create', default=False),
    cfg.BoolOpt('commit', default=True),
    cfg.BoolOpt('echo', default=True, help='是否显示回显'),
    cfg.BoolOpt('echo_pool', default=False, help='数据库连接池是否记录 checkouts/checkins操作'),
    cfg.IntOpt('pool_size', default=1000, help='数据库连接池中保持打开的连接数量'),
    cfg.IntOpt('pool_recycle', default=600, help='数据库连接池在连接被创建多久(单位秒)以后回收连接')
]

拼接选项

MYSQLCINDER_OPTS = (mysql_opts)

接着注册组,

CONF.register_group(mysql_opt_group)

最后将选项注册进组。

CONF.register_opts(MYSQLCINDER_OPTS, group=mysql_opt_group)

当然最重要的注册参数选项,我的理解就是暴露句柄。

# 注册参数选项
CONF = cfg.CONF

然后创建数据库引擎

common/utils/sqlalchemy_util.py


import logging
from json import loads as json_loads
 
from sqlalchemy.engine import create_engine
from sqlalchemy.pool import QueuePool
from confg import CONF
 
SQLALCHEMY_ENGINE_CONTAINER = {}
 
logger = logging.getLogger("arview")
 
 
def json_deserializer(s, **kw):
    if isinstance(s, bytes):
        return json_loads(s.decode('utf-8'), **kw)
 
    else:
        return json_loads(s, **kw)
 
 
def get_sqlalchemy_engine(db_url):
    if db_url not in SQLALCHEMY_ENGINE_CONTAINER:
        engine = create_engine(db_url, echo=CONF.db.echo,
                               # pool_pre_ping如果值为True,那么每次从连接池中拿连接的时候,都会向数据库发送一个类似
                               # select 1的测试查询语句来判断服务器是否正常运行。当该连接出现disconnect的情况时,
                               # 该连接连同pool中的其它连接都会被回收
                               pool_pre_ping=True,
                               echo_pool=CONF.db.echo_pool,
                               pool_size=CONF.db.pool_size,
                               pool_recycle=CONF.db.pool_recycle,
                               json_deserializer=json_deserializer,
                               poolclass=QueuePool)
        logger.info('Create sqlalchemy engine %s', engine)
        SQLALCHEMY_ENGINE_CONTAINER[db_url] = engine
 
    return SQLALCHEMY_ENGINE_CONTAINER[db_url]

这里引用配置文件的数据,直接引入CONF

from confg import CONF

然后使用

CONF.db.echo_pool

创建句柄,

 与我之前使用的方法不同的是,这里的数据库引擎不需要在使用的地方引入了,会在main里注册路由分组时,通过plugin插件自动将数据库引擎导入。这也是我有点搞不懂的地方,虽然更方便,但是不知道就很难知道了,问了同事才知道是怎么回事。

bottle源码


def install(self, plugin):
    ''' Add a plugin to the list of plugins and prepare it for being
        applied to all routes of this application. A plugin may be a simple
        decorator or an object that implements the :class:`Plugin` API.
    '''

plugin就是相当与golang中间件,不过作用范围是全部路由。

这里创建数据库句柄并使用是一个比较绕的过程。总体思路:

写一个bottle plugin,创建数据库句柄,然后install安装这个plugin。就可以在所有的路由中自动引入这个插件(就是不用在包里在导入db句柄了,bottle会自动导入)。

/common/base.py 创建plugin并安装


import logging
from bottle import Bottle
from confg.conf import CONF
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session
from db.models.base import Base as ApiModelBase
from common.utils.sqlalchemy_util import get_sqlalchemy_engine
from bottle_sqlalchemy import SQLAlchemyPlugin
 
logger = logging.getLogger("arview")
base = ApiModelBase  # sqlalchemy orm base class
 
 
class Plugins:
    SQLALCHEMY_PLUGIN = None  # sqlalchemy plugin, global only one instance
    APSCHEDULER_PLUGIN = None  # apsechduler plugin. global only one instance
 
 
class Base(object):
    def __init__(self, *args, **kwargs):
        logger.debug('>>>> Base init begin')
        self.app = Bottle()
        # self.app.install(swaggerPlugin(self._type))
 
        logger.debug('>>>> Base init end')
 
 
class DB(Base):
    def __init__(self, db_url, create=None, commit=None, *args, **kwargs):
        print('db_url:', db_url)
        super(DB, self).__init__(*args, **kwargs)
 
        if create is None:
            create = CONF.db.create
        if commit is None:
            commit = CONF.db.commit
 
        if Plugins.SQLALCHEMY_PLUGIN is None:
            Plugins.SQLALCHEMY_PLUGIN = _create_sqlalchemy_plugin(db_url, create=create, commit=commit)
        self.app.install(Plugins.SQLALCHEMY_PLUGIN)
        logger.debug("Install plugin: sqlalchemy.")
        # if CONF.api.enable_request_interval_plugin:
        #     self.app.install(RequestTimeIntervalPlugin())
        logger.debug('>>>> DB init end')
 
 
class CommonBase(object):
    def __init__(self):
        self._db = None
 
    @property
    def db(self):
        if not self._db:
            DBURL = "mysql+mysqlconnector://{}:{}@{}:{}/{}?charset=utf8".format(CONF.mysql.DbUser,
                                                                                CONF.mysql.DbPassWord,
                                                                                CONF.mysql.DbHost,
                                                                                CONF.mysql.DbPort,
                                                                                CONF.mysql.DbName)
            engine = create_engine(DBURL, echo=False)
            self._db = sessionmaker()(bind=engine)
        return self._db
 
    @db.deleter
    def db(self):
        if self._db:
            self._db.commit()
            self._db.close()
            self._db = None
 
 
def _create_sqlalchemy_plugin(db_url, create, commit):
    """
    创建sqlalchemy插件
    :param db_url:
    :param echo:
    :param create:
    :param commit:
    :return:
    """
 
    logger.debug('>>>> create sqlalchemy plugin begin')
    engine = get_sqlalchemy_engine(db_url)
    plugin = SQLAlchemyPlugin(engine, metadata=ApiModelBase.metadata, create=create, commit=commit, use_kwargs=True)
    logger.debug('>>>> create sqlalchemy plugin %s' % plugin)
    return plugin

最后使用

/api/user.py


import logging
 
from bottle import request
 
from common.base import DB
from api.service.user import UserService
 
logger = logging.getLogger("arview")
 
 
class User(DB, UserService):
 
    def __init__(self, *args, **kwargs):
        print(">>> User init begin")
        logging.debug('>>> User init begin')
        super(User, self).__init__(*args, **kwargs)
        self.dispatch()
        logger.debug('>>> User init end')
 
    def create(self, db=None):
        create_body = request.json
        create_data = self.create_user(create_body, db)
        return create_data
 
    def delete(self, db=None):
        delete_body = request.json
        delete_data = self.delete_user(delete_body, db)
        return delete_data
 
    def list(self, db=None):
 
        list_data = self.list_user(db)
        return list_data
 
    def dispatch(self):
        self.app.route('/listUser', method='post')(self.list)
        self.app.route('/createUser', method='post')(self.create)
        self.app.route('/deleteUser', method='post')(self.delete)

这里的db就不需要导入了,可以直接使用。

db层
主要是模型层 /db/model/user.py


from sqlalchemy import Column, String, Enum, TIMESTAMP, Boolean, Integer, BIGINT, DATETIME
 
from db.models.base import Base
 
 
class UserModel(Base):
    __tablename__ = "user"
    id = Column("id", BIGINT, primary_key=True, comment="用户id")
    created_at = Column("created_at", DATETIME, comment="创建时间")
    updated_at = Column("updated_at", DATETIME, comment="更新时间")
    deleted_at = Column("deleted_at", DATETIME, comment="删除时间")
    username = Column("username", String(20), comment="用户名")
    password = Column("password", String(500), comment="密码")
    role = Column("role", BIGINT, comment="角色")
 
    def __init__(self, id, created_at, updated_at, deleted_at, username, password, role):
        self.id = id
        self.created_at = created_at
        self.updated_at = updated_at
        self.deleted_at = deleted_at
        self.username = username
        self.password = password
        self.role = role

/db/model/base.py


from datetime import datetime
 
from sqlalchemy import Column, TIMESTAMP
from sqlalchemy.ext.declarative import declarative_base
 
 
# sqlalchemy orm base class
Base = declarative_base()
 
 
class TimestampMixin(object):
    """为ORM提供时间戳基类"""
 
    created_at = Column('created_at', TIMESTAMP(True), default=datetime.now,
                        comment=u"创建时间")
    updated_at = Column('updated_at', TIMESTAMP(True), default=datetime.now,
                        onupdate=datetime.now, comment=u"更新时间")

到此这篇关于Python bottle使用实例的文章就介绍到这了,更多相关python bottle使用内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: python中bottle使用实例代码

本文链接: https://www.lsjlt.com/news/11251.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • python中bottle使用实例代码
    模仿学习同事的代码来写的,主要是搞懂python中如何来组织包,如何调用包,如何读取配置文件,连接数据库,设置路由,路由分组。(注:使用的是python3.6) 整体目录设计如下: 根据调用层级从上往下来说: 首先...
    99+
    2022-06-02
    python bottle使用 python bottle
  • 如何在python中使用bottle框架
    这期内容当中小编将会给大家带来有关如何在python中使用bottle框架,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。python的数据类型有哪些python的数据类型:1. 数字类型,包括int(整型...
    99+
    2023-06-14
  • bottle框架如何在python 中使用
    这篇文章给大家介绍bottle框架如何在python 中使用,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。python有哪些常用库python常用的库:1.requesuts;2.scrapy;3.pillow;4.t...
    99+
    2023-06-14
  • Python使用PDFMiner解析PDF代码实例
    近期在做爬虫时有时会遇到网站只提供pdf的情况,这样就不能使用scrapy直接抓取页面内容了,只能通过解析PDF的方式处理,目前的解决方案大致只有pyPDF和PDFMiner。因为据说PDFMiner更适合...
    99+
    2022-06-04
    实例 代码 Python
  • Python heapq使用详解及实例代码
    Python heapq 详解 Python有一个内置的模块,heapq标准的封装了最小堆的算法实现。下面看两个不错的应用。 小顶堆(求TopK大) 话说需求是这样的: 定长的序列,求出TopK大的数据。...
    99+
    2022-06-04
    详解 实例 代码
  • 使用Python实现tail的示例代码
    目录前记1.第一版--从文件尾部读取实时数据2.第二版--实现tail -f3.第三版--优雅的读取输出日志文件前记 tail是一个常用的Linux命令, 它可以打印文件的后面n行数...
    99+
    2023-03-01
    Python实现tail Python tail
  • python实例方法的使用注意及代码实例
    1、实例方法是从属于实例对象的方法,定义实例方法时,第一个参数必须为 self。self 指当前的实例对象。 2、调用实例方法是,不需要也不能给 self 传值,self 由解释器自...
    99+
    2022-11-21
    python 实例方法
  • 使用python matplotlib画折线图实例代码
    目录matplotlib简介1、画折线图【一条示例】2、画折线图带数据标签3、画多条折线图:4、画多条折线图分别带数据标签:总结matplotlib简介 matplotlib 是py...
    99+
    2022-11-10
  • 使用python自动办公的实例代码
    包: 用来组织文件 包就是这样的,用来组织文件。 主要就是,用 from 包 .模块名字 或者 from 包 import 模块这样导入方式是我们需要注意的,包里面要有Init....
    99+
    2022-11-12
  • python实例方法使用代码怎么写
    这篇文章主要介绍“python实例方法使用代码怎么写”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“python实例方法使用代码怎么写”文章能帮助大家解决问题。实例方法是从属于实例对象的方法,定义实例...
    99+
    2023-07-04
  • Python实例代码分析
    这篇“Python实例代码分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Python实例代码分析”文章吧。1.交换两个变...
    99+
    2023-06-27
  • 使用Python对Csv文件操作实例代码
    csv是Comma-Separated Values的缩写,是用文本文件形式储存的表格数据,比如如下的表格: 就可以存储为csv文件,文件内容是: No.,Name,Age,Score 1,mayi,...
    99+
    2022-06-04
    实例 操作 代码
  • Python 字典的使用详解及实例代码
    目录字典长什么样字典内能放什么访问字典内容修改字典内容删除字典数据字典内置函数字典是Python实现散列表数据结构的形式,表现映射的关系,一对一。 字典长什么样 {}这是一个空字典,...
    99+
    2022-11-12
  • Python中sorted()用法案例代码
    目录Python中sorted()用法 sorted() 作为 Python 内置函数之一,其功能是对序列(列表、元组、字典、集合、还包括字符串)进行排序。 so...
    99+
    2023-02-27
    Python中sorted()用法 Python中sorted()
  • python muggle_ocr库用法及实例代码
    说明 muggle_ocr是一款轻量级的ocr识别库,对于python来说是识别率较高的图片验证码模块。 主要用于识别各种类型的验证码,一般文字提取效果稍差。 安装命令 pip install muggle_oc...
    99+
    2022-06-02
    python muggle_ocr库
  • Python 实现链表实例代码
    Python 实现链表实例代码 前言 算法和数据结构是一个亘古不变的话题,作为一个程序员,掌握常用的数据结构实现是非常非常的有必要的。 实现清单 实现链表,本质上和语言是无关的。但是灵活度却和实现它的语言密...
    99+
    2022-06-04
    实例 链表 代码
  • python代码实现烟花实例
    实现代码如下: # -*- coding: utf-8 -*- import math, random,time import threading import tkinter ...
    99+
    2022-11-12
  • Python定时器实例代码
    在实际应用中,我们经常需要使用定时器去触发一些事件。Python中通过线程实现定时器timer,其使用非常简单。看示例: import threading def fun_timer(): prin...
    99+
    2022-06-04
    定时器 实例 代码
  • Python pluggy框架使用示例代码
    目录实践环境例1 注册类函数为插件函数例2 注册模块函数为插件函数myhookspec.pymyhookimpl.pyother.pyexample.py例3:自定义插件类实现hoo...
    99+
    2022-11-11
  • python中Switch/Case实现的示例代码
    学习Python过程中,发现没有switch-case,过去写C习惯用Switch/Case语句,官方文档说通过if-elif实现。所以不妨自己来实现Switch/Case功能。 使用if…elif…el...
    99+
    2022-06-04
    示例 代码 python
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作