1. 2018-10-31 更新Logging日志记录以及异常捕获

感谢廖大教程。Python实战

直接在闲置的服务器上开发。阿里云Centos 6.8 64位

1 搭建开发环境

Python 环境是Python 3.4, 在装aiohttp的时候报错,之前用pip3和系统本身的pip(Python 2.7)也有安装问题,索性下最新版Python 3.6.4,并安装virtualenv独立运行。

  1. python3.3以后自带venv模块支持轻量级虚拟环境,virtualenv模块仍然支持,可安装。
  2. 1.创建虚拟环境
  3. virtualenv --no-site-packages myvenv
  4. 等价于
  5. virtualenv myvenv (目前新版默认不使用系统环境包)
  6. python3自带venv
  7. python -m venv myvenv
  8. 也是默认全新干净的环境,相反可选的参数
  9. python -m venv --system-site-packages myvenv
  10. 使虚拟环境指向系统环境包目录(非复制),在系统环境pip新安装包,在虚拟环境就可以使用。
  11. 2.激活虚拟环境
  12. Platform Shell Command to activate virtual environment
  13. Posix bash/zsh $ source <venv>/bin/activate
  14. fish $ . <venv>/bin/activate.fish
  15. csh/tcsh $ source <venv>/bin/activate.csh
  16. Windows cmd.exe C:> <venv>\Scripts\activate.bat
  17. PowerShell PS C:> <venv>\Scripts\Activate.ps1
  18. 3.关闭虚拟环境
  19. deactivate
  20. 4.删除虚拟环境
  21. 删除目录即可
  22. -by er爱喝果汁Q https://www.liaoxuefeng.com/discuss/001409195742008d822b26cf3de46aea14f2b7378a1ba91000/00150035599472221b683bc9ae245c4a08097bd0cc7866c000

所以直接运行:

  1. > python3.6 myvenv
  2. > source myvenv/bin/activate

之后就可以直接用Python命令而非Python3.6来指定使用版本了。

2 编写Web App骨架

原文中监听127.0.0.1:9000,本地测试直接打开即可,可是服务器怎么看页面呢。安装有nginx,但是配置太麻烦。想要快速查看页面。

服务器直接访问

阿里ECS管理页面中有公网和私网IP

在代码中重新监听私有IP的9000端口,然后访问公网IP:9000,无效。

将端口加入到安全组

之后,再次访问公网IP:9000。就成功了,不过是下载的形式。加上Content-Type即可:

  1. return web.Response(body=b'Awesome', headers={'content-type':'text/html'})
ERROR: address already in use

Ctrl+Z结束正在运行的Python进程后,再次python app.py出错

  1. error while attempting to bind on address ('172.*.*.*', 9000): address already in use
原因和解决办法
  1. ubuntu下,这个问题通常由于按ctrl+z结束程序造成。使用fg命令之后,按ctrl+c重新结束任务即可。
  2. CTRL-ZCTRL-C都是中断命令,但是他们的作用却不一样.
  3. CTRL-C是强制中断程序的执行,
  4. CTRL-Z的是将任务中断,但是此任务并没有结束,他仍然在进程中他只是维持挂起的状态,用户可以使用fg/bg操作继续前台或后台的任务,fg命令重新启动前台被中断的任务,bg命令把被中断的任务放在后台执行.
  5. 例如:
  6. 当你vi一个文件是,如果需要用shell执行别的操作,但是你又不打算关闭vi,因为你得
  7. 存盘推出,你可以简单的按下CTRL-Z,shell会将vi进程挂起~,当你结束了那个shell操作之后,你可以用fg命令继续vi你的文件.
  8. -by http://blog.csdn.net/helinbin/article/details/56015572

用了fg之后,确实又启动可以访问了:),用Ctrl+C结束后再次运行就没有地址占用错误提醒了。

  1. ##### 弃坑
  2. 3ORM 5节的Web框架。都比较难。而且对比GIT中的多个不明所以的函数后面的继续不下去了。虽然很想粗略的过一遍。但是算了,承认自己比较弱也是和自己的一种妥协。协程和装饰器还是理解的慢。以后再来补,一个月后再来挑战。 2018-3-1 17:48:24
  3. ##### 再次开始
  4. 2018917
  5. 服务器再次清零(试过好多东西,内部gitlaravel、练手的php框架),重新安装Python,只当作Python工具服务器用,只用Python实现,比如,想做一个距离懂你课程的倒计时来用退款鼓励自己。
  6. `腾讯云Centos 7.5 64位`
  7. 总之,现在做什么事情,就是要快!
  8. 网上各种资料一查,就必须要尽快搞定。
  9. 我也总是目标不明确,本来做A,中途遇到问题牵扯到的其他问题就都看了,其实目标只是AA才是主线,其他的都不重要。

3. 编写ORM

安装MariaDB、连接以及系统一些问题花费了小半天,遇到问题不少,如果刚开始就从手册走的话,就会清晰便捷很多。MariaDB使用MySQL连接器。

1). 非异步的ORM
  1. #! /usr/bin/python
  2. import pymysql as DB
  3. import datetime
  4. from hashlib import md5
  5. class Sql(object):
  6. def __init__(self):
  7. pass
  8. def sqlInit(self, dbInfo, mode='tuple'):
  9. """ sql初始化 """
  10. try:
  11. dbHost = dbInfo.get('host')
  12. dbUser = dbInfo.get('user')
  13. dbPasswd = dbInfo.get('passwd')
  14. dbName = dbInfo.get('db')
  15. conn = DB.connect(host=dbHost, user=dbUser, passwd=dbPasswd, db=dbName)
  16. if mode == 'tuple':
  17. cur = conn.cursor()
  18. else:
  19. cur = conn.cursor(DB.cursors.DictCursor)
  20. return conn, cur
  21. except Exception as e:
  22. self.log(e)
  23. print("connect failed.")
  24. exit()
  25. @classmethod
  26. def query(cls, sql, mode='tuple', **dbInfo):
  27. """ 查询 """
  28. conn, cur = cls().sqlInit(dbInfo, mode)
  29. try:
  30. cur.execute(sql)
  31. data = cur.fetchall()
  32. except Exception as e:
  33. Sql.log(e)
  34. Sql.log("error sql: " + str(sql))
  35. data = None
  36. conn.close()
  37. return data
  38. @classmethod
  39. def insert(cls, sql, param, **dbInfo):
  40. """ 插入 """
  41. conn, cur = cls().sqlInit(dbInfo)
  42. try:
  43. cur.executemany(sql, param)
  44. conn.commit()
  45. result = True
  46. except Exception as e:
  47. conn.rollback()
  48. Sql.log(e)
  49. Sql.log("error sql: " + str(sql))
  50. result = False
  51. conn.close()
  52. return result
  53. @classmethod
  54. def delete(cls, sql, param, **dbInfo):
  55. """ 删除 """
  56. conn, cur = cls().sqlInit(dbInfo)
  57. try:
  58. cur.execute(sql, param)
  59. conn.commit()
  60. result = True
  61. except Exception as e:
  62. Sql.log(e)
  63. Sql.log('error sql: ' + str(sql))
  64. conn.rollback()
  65. result = False
  66. conn.close()
  67. return result
  68. @classmethod
  69. def update(cls, sql, param, **dbInfo):
  70. """ 更新 """
  71. conn, cur = cls().sqlInit(dbInfo)
  72. try:
  73. cur.execute(sql, param)
  74. conn.commit()
  75. result = True
  76. except Exception as e:
  77. Sql.log(e)
  78. Sql.log('error sql: ' + str(sql))
  79. conn.rollback()
  80. result = False
  81. conn.close()
  82. return result
  83. @classmethod
  84. def run(cls, sql, **dbInfo):
  85. """ 执行其他语句 """
  86. conn, cur = cls().sqlInit(dbInfo)
  87. try:
  88. cur.execute(sql)
  89. result = True
  90. except Exception as e:
  91. Sql.log(e)
  92. Sql.log('error sql: ' + str(sql))
  93. result = False
  94. conn.close()
  95. return result
  96. @staticmethod
  97. def log(msg):
  98. """ 记录日志 """
  99. nowStr = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  100. fileName = datetime.datetime.now().strftime('%Y%m%d') + '.log'
  101. with open('./' + fileName, 'a') as f:
  102. f.write(str(nowStr) + '\n')
  103. if isinstance(msg, Exception):
  104. f.write("\tFile: %s, Line: %s.\n" % (msg.__traceback__.tb_frame.f_globals['__file__'], msg.__traceback__.tb_lineno))
  105. f.write('\t' + str(msg) + '\n')
  106. dbInfo = {
  107. 'host': '127.0.0.1',
  108. 'user': 'root',
  109. 'passwd': '123456',
  110. 'db': 'test_xxxx'
  111. }
  112. try:
  113. print("1. 建表")
  114. if not Sql.run("DROP TABLE IF EXISTS `user`", **dbInfo):
  115. raise Exception('drop error')
  116. sql = '''
  117. CREATE TABLE `user`(
  118. `id` int(11) NOT NULL AUTO_INCREMENT,
  119. `name` varchar(255) NOT NULL,
  120. `password` varchar(64) NOT NULL,
  121. `created` varchar(64) NULL,
  122. `updated` varchar(64) NULL,
  123. `deleted` varchar(64) NULL,
  124. `status` int(1) NOT NULL DEFAULT 1,
  125. PRIMARY KEY (`id`)
  126. ) ENGINE = InnoDB;
  127. '''
  128. if not Sql.run(sql, **dbInfo):
  129. raise Exception('建表失败!')
  130. print('2. 插入')
  131. sql = "INSERT INTO `user`(name, password, created, status) VALUES (%s, %s, %s, %s)"
  132. param = [['admin', md5(b'123456').hexdigest(), datetime.datetime.now(), 1]]
  133. Sql.insert(sql, param, **dbInfo)
  134. print('3. 查询')
  135. data = Sql.query("select * from user", 'tuple', **dbInfo)
  136. print(data)
  137. print('4. 更新')
  138. Sql.update("UPDATE `user` set name = %s, updated = %s where id = %s", ('admin2', datetime.datetime.now(), 1), **dbInfo)
  139. data = Sql.query("select * from user", 'dict', **dbInfo)
  140. print(data)
  141. print('5. 删除')
  142. Sql.delete("DELETE FROM `user` where id = %s", 1, **dbInfo)
  143. data = Sql.query("select * from user", 'tuple', **dbInfo)
  144. print(data)
  145. except Exception as e:
  146. print('error: '+str(e))

执行结果

  1. 1. 建表
  2. 2. 插入
  3. 3. 查询
  4. ((1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', '2018-10-04 21:52:13.543246', No
  5. ne, None, 1),)
  6. 4. 更新
  7. [{'id': 1, 'name': 'admin2', 'password': 'e10adc3949ba59abbe56e057f20f883e', 'crea
  8. ted': '2018-10-04 21:52:13.543246', 'updated': '2018-10-04 21:52:13.553830', 'dele
  9. ted': None, 'status': 1}]
  10. 5. 删除
  11. ()

用了两种查询方法tuple dict.

  1. def cursor(self, cursor=None):
  2. """
  3. Create a new cursor to execute queries with.
  4. :param cursor: The type of cursor to create; one of :py:class:`Cursor`,
  5. :py:class:`SSCursor`, :py:class:`DictCursor`, or :py:class:`SSDictCursor`.
  6. None means use Cursor.
  7. """
  8. if cursor:
  9. return cursor(self)
  10. return self.cursorclass(self)

有一个简单日志记录错误。整体很简单粗糙,不能称之为ORM,只是简单的增删改查操作。

2).异步的ORM

照着廖大的抄了一遍,再看了justoneliu的ORM注释理解了一下没懂的地方。

还有需要修改的地方,比如Logging.info输出如何输出log文件,输出中args丢失,更新数据未指定列全部成了默认值。不影响主进度日志待定,先完善一下输出。

4. 编写Model

Model小节也简单过了一遍,应该有个生成脚本直接通过各表Model去生成sql。

5. 编写WEB框架

这里感觉也好难理解呢。python之aiohttp源码解析——add_route和middleware的工作方式 ,aiohttp的middleware为啥有两个参数,倒序的包含handle又是怎么回事?还是没有理解。官方文档aiohttp middlewares中都用了@web.middleware修饰了,大概看一下流程,以后再来搞懂吧。真头大,每次看到这些很难懂的都感觉自己很笨。

6. 配置

配置我直接复制重命名.bak了一份,开发时自己去掉就好了。

7. 编写MVC

希望可以顺利启动哈哈。orm webframe app 都很紧张呢。

这里终于要建handlers.py了,之前app.py运行会报错

  1. INFO:root:Model into metaclass ,yeeeeeeeeee
  2. DEBUG:asyncio:Using selector: EpollSelector
  3. INFO:root:create database connection pool...
  4. ./app.py:107: DeprecationWarning: loop argument is deprecated
  5. logger_factory, response_factory
  6. INFO:root:init jinja2...
  7. INFO:root:set jinja2 template path: /data/webapp/templates
  8. Traceback (most recent call last):
  9. File "./app.py", line 118, in <module>
  10. loop.run_until_complete(init(loop))
  11. File "/usr/local/lib/python3.7/asyncio/base_events.py", line 568, in run_until_complete
  12. return future.result()
  13. File "./app.py", line 111, in init
  14. add_routes(app, 'handlers')
  15. File "/data/webapp/webFrame.py", line 169, in add_routes
  16. mod = __import__(module_name, globals(), locals())
  17. ModuleNotFoundError: No module named 'handlers'

Ok

8. 构建前端

  1. blogs = [
  2. Blog(id='1', name='Test Blog', summary=summary, created_at=time.time()-120),
  3. Blog(id='2', name='Something New', summary=summary, created_at=time.time()-3600),
  4. Blog(id='3', name='Learn Swift', summary=summary, created_at=time.time()-7200)
  5. ]

这块没理解,调了几次发现只是因为Blog(dict)继承自dict, 就直接转为dict了。Ohhhhhhh

本节没有按照原文用uikit css框架,直接写一个最简单的html,用一个jquery cdn就够用了。类似这个很像文档的文章,我想要的博客就是这样的,简单不做作,有干货,虽然我还差好多

python实战博客的更多相关文章

  1. python学习博客地址集合。。。

    python学习博客地址集合...   老师讲课博客目录 http://www.bootcdn.cn/bootstrap/  bootstrap cdn在线地址 http://www.cnblogs. ...

  2. 用Python编写博客导出工具

    用Python编写博客导出工具 罗朝辉 (http://kesalin.github.io/) CC 许可,转载请注明出处   写在前面的话 我在 github 上用 octopress 搭建了个人博 ...

  3. 原创翻译-值得关注的10个python语言博客

    原文链接 原文链接的网页感觉网络不是很好,不容易上.我在这里就给大家做个翻译吧. 大家好,还记得我当时学习python的时候,我一直努力地寻找关于python的博客,但我发现它们的数量很少.这也是我建 ...

  4. 值得关注的10个python语言博客(转)

    大家好,还记得我当时学习python的时候,我一直努力地寻找关于python的博客,但我发现它们的数量很少.这也是我建立这个博客的原因,向大家分享我自己学到的新知识.今天我向大家推荐10个值得我们关注 ...

  5. 值得关注的10个python语言博客

    大家好,还记得我当时学习python的时候,我一直努力地寻找关于python的博客,但我发现它们的数量很少.这也是我建立这个博客的原因,向大家分享我自己学到的新知识.今天我向大家推荐10个值得我们关注 ...

  6. Python大婶博客汇总

    Python大神金星 博客:http://www.cnblogs.com/jin-xin/articles/7459977.html

  7. 【Python】博客信息爬取-微信消息自动发送

    1.环境安装 python -m pip install --upgrade pip pip install bs4 pip install wxpy pip install lxml 2.博客爬取及 ...

  8. GIT团队实战博客

    项目要求 组长博客 遇到的困难及解决办法 组员1(组长):王彬 遇到的困难  在团队任务分工的时候没有充分照顾到所有人,导致队员们的工作量不均. 现场编程时间不够 解决办法 在此对组员们表示抱歉,由于 ...

  9. python十个博客

    1.首先第一个肯定是毋庸置疑的Planet Python这是最出名的python博客其中之一,快去看看,我希望你能找到对你有用的东西,昨天它还更新了呢! 2.第二个博客是lucumr,博主是flask ...

随机推荐

  1. VirtualBox fedora29 安装

    目录 准备工作 VirtualBox安装 fedora安装 快捷键定义 准备工作 平台配置 win10 64位 内存 8G 硬盘 1T 下载地址 VirtualBox 5.2.22:https://w ...

  2. MyEclipse中点击部署项目无响应(Deploy MyEclipse J2EE Project to Server)

    大部分情况下,只要找到当前的工作空间,删除其中一个文件就可以. 这个文件在Myeclipse工作.metadata\.plugins\org.eclipse.core.runtime\.setting ...

  3. 关于Excel导出实例(适合新手,比较详细)

    需要源代码的可以加我微信好友gqljxg1514 1,首先配置依赖pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0&q ...

  4. TensorFlow 算术运算符

    TensorFlow 算术运算符 TensorFlow 提供了几种操作,您可以使用它们将基本算术运算符添加到图形中. tf.add tf.subtract tf.multiply tf.scalar_ ...

  5. git的基本用法——我的日常使用

    git的基本用法 一,前言 网上有太多关于git的用法说明,而我看得云里雾里,可能是本人比较愚笨.平常时间老问别人又觉得很不好意思,估计大多的同学们都是自己解决.后来我想到了买一本书,淘宝上git书籍 ...

  6. python自学第10天,生成器

    列表生成式 print([i*2 for i in range(10)])#这就是列表生成式 #相当于下面的代码 a=[] for i in range(10): a.append(i*2) prin ...

  7. 蓝牙协议分析(10)_BLE安全机制之LE Encryption

    1. 前言 前面文章介绍了两种BLE的安全机制:白名单[4]和LL privacy[3].说实话,在这危机四伏的年代,这两种“捂着脸讲话(其它人不知道是谁在讲话,因而不能插话.不能假传圣旨,但讲话的内 ...

  8. 一轮冲刺(NABCD)和需求分析

    N我们的创意是为了解决我们测量人员在测量结束后要计算一些数据的问题,当我们观测角度后,有大量的角度需要计算,有时会用到角度与弧度的转换. A我们测量人员知道计算的公式,了解一些c++和c# B我们这个 ...

  9. Redis学习第六课:Redis ZSet类型及操作

    Sorted set是set的一个升级版本,它在set的基础上增加了一个顺序属性,这一属性在添加修改元素时候可以指定,每次指定后,zset会自动重新按新的值调整顺序.可以理解为有两列字段的数据表,一列 ...

  10. L2-018. 多项式A除以B*

    L2-018. 多项式A除以B 参考博客 #include <iostream> #include <map> #include <cmath> #include ...