一. socket过程中注意的点

1. 黏包问题

所谓的黏包就是指,在TCP传输中,因为发送出来的信息,在接受者都是从系统的缓冲区里拿到的,如果多条消息积压在一起没有被读取,则后面读取时可能无法分辨消息之间的分隔,造成读取的时候把前后多条消息的内容连起来读出来,就造成了错误。比较靠谱的解决方式是:一端在发送完消息以后,需要接收一次消息,另一端在第一次接收完消息以后,发送一次消息,这样间隔处理;这样就会保证每次接收的消息都是完整到结束的,因为对方在每次发送完整消息以后,都会接收消息以停止发送。在接收长消息的时候,可以先发送长度,然后接收端根据长度迭代不断接收信息。

2. socketserver库

在写一个基础的socket的服务端时,我们需要做建立socket、绑定端口、开启监听、阻塞在等待连接(以获得连接的地址和socket),这样几个步骤。如下图所示:

服务端流程示例代码

此外这样的过程是无法并发的,也就是说同一个server同时只能连接一个client并接受其请求,其他client都是被阻塞的(在listen范围内的是会等待,其他则无法连接),等到连接的client断开连接后,才能连接上。

但是我们可以使用socketserver!这个库的一些对象及其方法,封装了上面的一系列动作,我们只需要简单传入需要绑定的地址端口,并使用其方法启动server即可。而且socketserver可以通过io多路复用、多进程、多线程等方式支持服务多个客户端的连接,且并不需要我们自己实现或修改代码。

二. python的logging 模块

1. python中的logging模块,能够比较方便地帮我们管理写日志的一些流程,封装了文件处理、控制台输出、控制输出的样式一系列操作,非常简单易用。

官方文档流程图:

2. 下面是我写的一段简单示例:

 import logging, os
import util as UT def set_logger(log_name):
logger = logging.getLogger(log_name)
logger.setLevel(logging.DEBUG) # 这是设置写日志文件的句柄
# 文件路径随意...如果是写得相对路径,会在具体调用的文件的相对路径
# 所以会导致不同调用不同位置,还是绝对路径好。
# FileHandler默认模式为追加。
fh = logging.FileHandler(os.path.join(UT.PROJECT_DIR, '%s.log' % log_name))
fh.setLevel(logging.DEBUG) # 该句柄用于输出到控制台;
# 单独只有上面一个句柄,控制台里没有输出。
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG) # 写文件的句柄还可以设定固定的一些样式
# 比如这里写的是输出的时间,句柄名,log级别,然后是具体信息
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter) # 添加句柄给日志
logger.addHandler(fh)
logger.addHandler(ch) return logger # 我在这里写了两个日志,这样在其他文件import这两个日之后
# 就会一直保持追加写入,类似单例的效果 logger_err = set_logger('error')
logger_flow = set_logger('flow')

3. logging的示例可以设置多种警告级别,从debug,info,warn,error到critial,都是方法可以直接调用,会在日志里面警告级别的地方显示出来。

调用的地方示例:

 import MyLogging as ML

 try:
msg = 'AAAAAAA'
ML.logger_flow.info(msg) except Exception as e:
ML.logger_err.error(e)

4. logging还有些其他的方法比如Filter。限制只有满足过滤规则的日志才会输出。

比如我们定义了filter = logging.Filter('a.b.c'),并将这个Filter添加到了一个Handler上,则使用该Handler的Logger中只有名字带a.b.c前缀的Logger才能输出其日志。

示例如下:

 filter = logging.Filter('flow.aaa.bbb')
fh.addFilter(filter)

5. 我们在生产中其实会遇到一个更常见的问题,就是可能会一直打印日志,因为日志文件一直追加,所以日志文件会越来越大。这种时候我们就需要rotation功能,要日志在写满一定大小,或者根据时间自动去拆分,

等到满足条件以后,就写到一个新的文件里。logging模块是可以设置的。

此时需要使用RotatingFileHandler或者TimedRotatingFileHandler,前者是按照文件大小分割,后者按照时间。使用示例如下:

 from logging.handlers import RotatingFileHandler as RFHandler

 # maxBytes是设定最大大小,backupCount是最多备份文件个数
# 默认模式为a 即追加
fh = RFHandler('aaa.log', maxBytes=1024 * 1024 * 100, backupCount=10, delay=0.05) # 后面的使用与普通FileHandler一样
fh.setLevel(logging.DEBUG)

但是我在使用中曾经发现,python自带的logging模块的Rotataion句柄,在面对并发的时候,处理rotation的效果非常之诡异!有时候写到了各种不同的log的备份里,有时候log的备份文件又不是按照时间流写的...总之有问题,并发不安全...

然后我发现一个第三方的句柄是安全的,叫cloghandler,大家可以试试!使用的方法完全一致~

 # 像这样用好了,完全一致的
try:
from cloghandler import ConcurrentRotatingFileHandler as RFHandler
except ImportError:
from warnings import warn
warn("ConcurrentLogHandler package not installed. Using builtin log handler")
from logging.handlers import RotatingFileHandler as RFHandler

三. 第三方库“Q”!

既然提到了logging,我再介绍个挺有用的很小的第三方库,叫Q。其作用是更简单地封装了一些写日志的操作...如果你需要在一些情况下临时增加打印调试问题,可以用用~(我只在生产的linux环境上玩过,也不造win下咋样的能不能用...)

使用 "pip install -U q"来安装,默认会把日志追加输出到 /tmp/q 这个文件里。如果设置了$TMPDIR环境变量,输出将会保存在$TMPDIR/q文件中。我们也可以设置环境变量TEMP、TEMPDIR和TMP来替代TMPDIR环境变量。

想要打印的简单,示例:

 import q

 a = 'da1e1'
q(a)

这样就可以了,在log里,q会自动带上打印的文件信息、位置、时间、耗时、变量类型等等...是不是超方便的...如果打印的是个内容非常大的,q还会在/tmp下生成一个对应的完整内容的日志,在q里就只是显示一部分。

甚至可以不用定义变量,直接打印表达式,或者直接插入到运行的代码里也是可以的,不会影响代码执行。示例如下:

 # 打印(seq or '')
file.write(prefix + q(seq or '').join(items))
# 打印变量prefix
file.write(q/prefix + (seq or '').join(items))
# 打印变量prefix
file.write(q|prefix + (seq or '').join(items)) #用q(), \, |三种方式效果是一样的,就看怎么方便吧

想要追踪函数的参数和返回值,将q当做一个装饰器使用!示例如下:

 import q

 @q
def a(a1, a2):
return a1 + a2

还可以在代码任意地方调用 q.d(),启动交互控制台。

综上,是不是超级特级方便好用!!!!!在没法debug,不能用pdb,或者复杂的并发情况下,这种打印真是太提高调试效率了~~~

python基础整理笔记(九)的更多相关文章

  1. python基础整理笔记(五)

    一. python中正则表达式的一些查漏补缺 1.  给括号里分组的表达式加上别名:以便之后通过groupdict方法来方便地获取. 2.  将之前取名为"name"的分组所获得的 ...

  2. python基础整理笔记(四)

    一. python 打开文件的方法 1. python中使用open函数打开文件,需要设定的参数包括文件的路径和打开的模式.示例如下: f = open('a.txt', 'r+') 2. f为打开文 ...

  3. python基础整理笔记(一)

    一. 编码 1. 在python2里,加载py文件会对字符进行编码,需要在文件头上的注释里注明编码类型(不加则默认是ascII). # -*- coding: utf-8 -*- print 'hel ...

  4. python基础整理笔记(八)

    一. python反射的方式来调用方法属性 反射主要指的就是hasattr.getattr.setattr.delattr这四个函数,作用分别是检查是否含有某成员.获取成员.设置成员.删除成员. 此外 ...

  5. python基础整理笔记(七)

    一. python的类属性与实例属性的注意点 class TestAtt(): aaa = 10 def main(): # case 1 obj1 = TestAtt() obj2 = TestAt ...

  6. python基础整理笔记(三)

    一. python的几种入参形式:1.普通参数: 普通参数就是最一般的参数传递形式.函数定义处会定义需要的形参,然后函数调用处,需要与形参一一对应地传入实参. 示例: def f(a, b): pri ...

  7. python基础整理笔记(二)

    一. 列表 1. 创建实例: a = [1,2,3] b = list() 2. 主要支持的操作及其时间复杂度如下: 3. 其他 python中的列表,在内存中实际存储的形式其实是分散的存储,比较类似 ...

  8. python基础整理笔记(六)

    一. 关于hashlib模块的一些注意点 hashlib模块用于加密相关的操作,代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512, MD ...

  9. 0003.5-20180422-自动化第四章-python基础学习笔记--脚本

    0003.5-20180422-自动化第四章-python基础学习笔记--脚本 1-shopping """ v = [ {"name": " ...

随机推荐

  1. 初学c# -- 学习笔记(五) winfrom自定义滚动条

    找了些例子,要么庞大.要么搞个安装组件什么的,我要求能用就行了.实在找例子修改麻烦,就做了一个.其实实现挺简单,就是panel或图片什么的跟着鼠标走就行了. 这里panel自己可以加背景图或直接搞个图 ...

  2. (转载)IE6支持透明PNG图片解决方案:DD_belatedPNG.js

    DD_belatedPNG.js 是一个能是IE6支持p显示ng透明图片,而且还支持背景循环(background-repeat)和定位(backgrond-position) ,支持focus,Ho ...

  3. tcp转发

    Proxy.java package com.dc.tcp.proxy; import java.io.IOException; import java.net.ServerSocket; impor ...

  4. python 2.4 与 python 3.0 的比较

    转过来,留着日后查看 [转自:]http://hi.baidu.com/autoitcn/blog/item/5f41973294b5fc4fac4b5f77.html python 2.4 与 py ...

  5. db2 with ur

    这几天查询DB2数据库,老遇到select * from XXX with ur, 好奇ur是什么作用,现在记录一下. DB2中,共有四种隔离级:RS,RR,CS,UR,DB2提供了这4种不同的保护级 ...

  6. 配置Eclipse编写HTML/JS/CSS/JSP页面的自动提示。

    我们平时用eclipse开发jsp页面时智能提示效果不太理想,今天用了两个小时发现了eclipse也可以像Visual Studio 2008那样完全智能提示HTML/JS/CSS代码,使用eclip ...

  7. C# 动软生成器对应的Access数据库操作类DbHelperOleDb

    using System;using System.Collections;using System.Collections.Specialized;using System.Data;using S ...

  8. 查看Oracle中是否有锁表的sql

    1.查看是否有锁表的sql 代码如下: select 'blocker('||lb.sid||':'||sb.username||')-sql:'|| qb.sql_text blockers, 'w ...

  9. IntelliJ IDEA 2016.2激活方法

    IntelliJ IDEA 2016.2激活 激活码 43B4A73YYJ-> eyJsaWNlbnNlSWQiOiI0M0I0QTczWVlKIiwibGljZW5zZWVOYW1lIjoib ...

  10. python 入门学习之环境搭载

    1.常用python 2.7 需要在我的电脑环境变量进行环境搭载 2.用notepad++进行编辑器适配,选择python语言 在输入运行程序名里面输入cmd /k x: & cd " ...