模块调用,datetime,time,logging,递归,双层装饰器, json,pickle迭代器和生成器

一.python模块(导入,内置,自定义,开源)

1.模块简介

模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py。模块可以被别的程序引入,以使用该模块中的函数等功能。这也是使用python标准库的方法。

类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合。而对于一个复杂的功能来,可能需要多个函数才能完成(函数又可以在不同的.py文件中),n个 .py 文件组成的代码集合就称为模块。

2.模块的引入

在Python中用关键字import来引入某个模块,比如要引用模块math,就可以在文件最开始的地方用import math来引入。在调用math模块中的函数时,必须这样引用:

模块名.函数名
例:
import sys
import module

有时候我们只需要用到模块中的某个函数,只需要引入该函数即可,此时可以通过语句

from 模块名 import 函数名1,函数名2....

例:

import module
#从某个模块导入某个功能
from module.xx.xx import xx
#从某个模块导入某个功能,并且给他个别名
from module.xx.xx import xx as rename  
#从某个模块导入所有
from module.xx.xx import *

 模块分为三种

  • 自定义模块
  • 内置模块
  • 开源模块

#安装模块的几种方式

(1)yum,pip安装:http://www.ttlsa.com/python/how-to-install-and-use-pip-ttlsa/

(2)源码安装

需要编译环境:yum install python-devel gcc
下载源码包:wget http://xxxxxxxxxxx.tar
解压:tar -xvf xxx.tar
进入:cd xxx
编译:python setup.py build
安装:python setup.py install

自定义模块导入

1.在Python中,每个Python文件都可以作为一个模块,模块的名字就是文件的名字。

写一个自定义模块(模块文件要和调用该模块的程序在同一目录下)

#s4.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#  Author: Jason Wang

def login():
    print("login")

def logout():
    print('logout')

 

#执行s3输出: login

2.模块文件为单独文件夹,文件夹和程序在同一目录

导入模块其实就是告诉Python解释器去解释那个py文件

  • 导入一个py文件,解释器解释该py文件
  • 导入一个包,解释器解释该包下的 __init__.py 文件

3.sys.path添加目录

如果sys.path路径列表没有你想要的路径,可以通过 sys.path.append('路径') 添加。
通过os模块可以获取各种目录,如果自定义模块的目录机构包含两级文件目录,可以将第一级父目录加到path变量中例如:

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
#os.path.abspath(__file__)获取文件的绝对路径,os.path.dirname获取此文件的父目录,此例子为将Atm_shopping加入到系统path路径中去

 内置模块

1.os模块 提供系统级别的操作

os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径

>>> os.getcwd()
'/Users/JasonWang/PycharmProjects/sd13'

 os.chdir("目录名") 改变当前脚本工作目录;相当于linux下cd命令

>>> os.chdir('/usr')
>>> os.getcwd()
'/usr'
>>> 

 os.curdir 返回当前目录: ('.')

>>> os.curdir
'.'

 os.pardir 获取当前目录的父目录字符串名:('..')

>>> os.pardir
'..'

 os.makedirs('目录1/目录2') 可生成多层递归目录(相当于linux下mkdir -p)

>>> os.makedirs('test/a1')
>>> os.listdir()
['__pycache__', 'account.py', 'commons.py', 'index.py', 'manager.py', 'maopao.py', 'test']

 os.removedirs('目录') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推

>>> os.removedirs('test/a1')
>>> os.listdir()
['__pycache__', 'account.py', 'commons.py', 'index.py', 'manager.py', 'maopao.py']
>>> 
#a目录中除了有一个b目录外,再没有其它的目录和文件。
#b目录中必须是一个空目录。 如果想实现类似rm -rf的功能可以使用shutil模块

 os.mkdir('目录') 生成单级目录;相当于shell中mkdir 目录

>>> os.mkdir('test')
>>> os.listdir()
['__pycache__', 'account.py', 'commons.py', 'index.py', 'manager.py', 'maopao.py', 'test']

 os.rmdir('目录') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir

>>> os.rmdir('test')
>>> os.listdir()
['__pycache__', 'account.py', 'commons.py', 'index.py', 'manager.py', 'maopao.py']

 os.listdir('目录') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印

os.remove()删除一个文件

os.rename("原名","新名") 重命名文件/目录

>>> os.rename('test','test1')
>>> os.listdir()
['__pycache__', 'account.py', 'commons.py', 'index.py', 'manager.py', 'maopao.py', 'test1']

os.stat('path/filename') 获取文件/目录信息

>>> os.stat('test1')
os.stat_result(st_mode=16877, st_ino=2841750, st_dev=16777220, st_nlink=2, st_uid=501, st_gid=20, st_size=68, st_atime=1465982539, st_mtime=1465982462, st_ctime=1465982462)
>>> 

 os.sep 输出操作系统特定的路径分隔符,win下为"\",Linux下为"/"

>>> os.sep
'/'

 os.pathsep 输出用于分割文件路径的字符串

>>> os.pathsep ':'

os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix'

>>> os.name
'posix'

 os.system("linux命令") 运行shell命令,直接显示

>>> os.system('uptime')
 9:38  up 15 mins, 1 user, load averages: 2.24 2.55 2.02
0

os.environ 系统环境变量

>>> os.environ

 os其他语法

os.path模块主要用于文件的属性获取,
os.path.abspath(path)  返回path规范化的
*os.path.split(path)  将path分割成目录和文件名二元组返回
*os.path.dirname(path)  返回path的目录。其实就是os.path.split(path)的第一个元素
*os.path.basename(path)  返回path最后的文件名。如何path以/或结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.exists(path)  如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path)  如果path是绝对路径,返回True
os.path.isfile(path)  如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path)  如果path是一个存在的目录,则返回True。否则返回False
*os.path.join(path1[, path2[, ...]])  将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path)  返回path所指向的文件或者目录的最后存取时间
os.path.getmtime(path)  返回path所指向的文件或者目录的最后修改时间

 2、sys模块 用于提供对解释器相关的操作

sys.argv   命令行参数List,第一个元素是程序本身路径
sys.modules 返回系统导入的模块字段,key是模块名,value是模块
sys.exit(n)        退出程序,正常退出时exit(0)
sys.version        获取Python解释程序的版本信息
sys.maxint         最大的Int值
sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform       返回操作系统平台名称
sys.stdout.write('please:')
val = sys.stdin.readline()[:-1]
sys.modules.keys() 返回所有已经导入的模块名
sys.modules.values() 返回所有已经导入的模块
sys.exc_info()     获取当前正在处理的异常类,exc_type、exc_value、exc_traceback当前处理的异常详细信息
sys.exit(n)        退出程序,正常退出时exit(0)
sys.hexversion     获取Python解释程序的版本值,16进制格式如:0x020403F0
sys.version        获取Python解释程序的
sys.api_version    解释器的C的API版本
sys.version_info
‘final’表示最终,也有’candidate’表示候选,serial表示版本级别,是否有后继的发行
sys.displayhook(value)      如果value非空,这个函数会把他输出到sys.stdout,并且将他保存进__builtin__._.指在python的交互式解释器里,’_’ 代表上次你输入得到的结果,hook是钩子的意思,将上次的结果钩过来
sys.getdefaultencoding()    返回当前你所用的默认的字符编码格式
sys.getfilesystemencoding() 返回将Unicode文件名转换成系统文件名的编码的名字
sys.setdefaultencoding(name)用来设置当前默认的字符编码,如果name和任何一个可用的编码都不匹配,抛出 LookupError,这个函数只会被site模块的sitecustomize使用,一旦别site模块使用了,他会从sys模块移除
sys.builtin_module_names    Python解释器导入的模块列表
sys.executable              Python解释程序路径
sys.getwindowsversion()     获取Windows的版本
sys.copyright      记录python版权相关的东西
sys.byteorder      本地字节规则的指示器,big-endian平台的值是’big’,little-endian平台的值是’little’
sys.exc_clear()    用来清除当前线程所出现的当前的或最近的错误信息
sys.exec_prefix    返回平台独立的python文件安装的位置
sys.stderr         错误输出
sys.stdin          标准输入
sys.stdout         标准输出
sys.platform       返回操作系统平台名称
sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.maxunicode     最大的Unicode值
sys.maxint         最大的Int值
sys.version        获取Python解释程序的版本信息
sys.hexversion     获取Python解释程序的版本值,16进制格式如:0x020403F0

 3.时间模块

1)time模块

时间戳计算机时间的一种表示方式,是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。

time.time()

>>> import time
>>> time.time()
1466041557.853502

time.ctime()

>>> time.ctime()#将时间戳转化为字符串格式Thu Jun 16 09:49:10 2016,默认是当前系统时间的时间戳
'Thu Jun 16 09:49:10 2016'
>>> time.ctime(time.time()-3600)#ctime可以接收一个时间戳作为参数,返回该时间戳的字符串形式 Wed Thu Jun 16 08:49:33 2016'
'Thu Jun 16 08:49:33 2016'

 time.gtime()

>>> time.gmtime()#将时间戳转化为struct_time格式,默认是当前系统时间戳
time.struct_time(tm_year=2016, tm_mon=6, tm_mday=16, tm_hour=1, tm_min=52, tm_sec=57, tm_wday=3, tm_yday=168, tm_isdst=0)
>>> time.gmtime(time.time()-3600)
time.struct_time(tm_year=2016, tm_mon=6, tm_mday=16, tm_hour=0, tm_min=53, tm_sec=18, tm_wday=3, tm_yday=168, tm_isdst=0)
说明:
struct_time格式也是一种时间表现形式,其实有点类似列表或元祖的形式
共有九个元素,分别表示,同一个时间戳的struct_time会因为时区不同而不同顺序为
年 tm_year
月 tm_mon
日 tm_mday
小时 tm_hour
分钟 tm_min
秒 tm_sec
周 tm_wday,注意周是从0开始计数的,也就是周一是0
一年中的第几天 tm_yday
是否是夏令日 tm_isdst(也没啥卵用)

 time.localtime()

>>> time.localtime()# 同样是将时间戳转化为struct_time,只不过显示的是本地时间,gmtime显示的是标准时间(格里尼治时间)
time.struct_time(tm_year=2016, tm_mon=6, tm_mday=16, tm_hour=9, tm_min=55, tm_sec=24, tm_wday=3, tm_yday=168, tm_isdst=0)

 time.mktime()

>>> time.mktime(time.localtime())# 将struct_time时间格式转化为时间戳
1466042217.0

 time.strftime()

>>> time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())# 将struct_time时间格式转化为自定义的字符串格式
'2016-06-16 09:58:43'
说明:
"%Y-%m-%d %H:%M:%S"就是我们自定义的字符串个"%Y有点类似于占位符

 time.strptime()

>>> time.strptime("2016-06-16","%Y-%m-%d")# 与trftime相反,将字符串格式转化为struct_time格式
time.struct_time(tm_year=2016, tm_mon=6, tm_mday=16, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=168, tm_isdst=-1)
说明:
第一个参数是时间的字符串形式,第二个参数是第一个参数的格式,格式要与字符串对应
另外时分秒默认是0,可以省略,但是年月日不可以省

 time.asctime()

>>> time.asctime(time.localtime())# 将struct_time转化为字符串形式
'Thu Jun 16 10:05:42 2016'

 datetime模块

  • datetime.date:表示日期的类。常用的属性有year, month, day
  • datetime.time:表示时间的类。常用的属性有hour, minute, second, microsecond
  • datetime.datetime:表示日期时间
  • datetime.timedelta: 表示时间间隔,即两个时间点之间的长度
datetime.date.today()
>>> datetime.date.today()# 返回当前日期的字符串形式2016-02-17
datetime.date(2016, 6, 16)
>>> print(datetime.date.today())
2016-06-16
datetime.datetime.now()
>>> print( datetime.datetime.now())#返回的时间的字符串形式
2016-06-16 10:10:37.612443
>>> print( datetime.datetime.now().timestamp())# 转化为struct_time格式
1466043058.141845
 datetime.date.fromtimestamp()
>>> datetime.date.fromtimestamp(time.time()- 3600 *24)
datetime.date(2016, 6, 15)
>>> print(datetime.date.fromtimestamp(time.time()- 3600 *24))
2016-06-15

  datetime.timedelta()

datetime.timedelta()返回的是一时间间隔对象,常与datetime.datetime.now()合用计算时间

>>> print(datetime.datetime.now() - datetime.timedelta(days = 2))
2016-06-14 10:27:09.652336

 三、递归

    在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解。
递归算法解决问题的特点:
(1) 递归就是在过程或函数里调用自身。
(2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
(3) 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。
(4) 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序。
递归算法所体现的“重复”一般有三个要求:
(1) 每次调用在规模上都有所缩小(通常是减半);
(2) 相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入);
(3) 在问题的规模极小时必须用直接给出解答而不再进行递归调用,因而每次递归调用都是有条件的(以规模未达到直接解答的大小为条件),无条件递归调用将会成为死循环而不能正常结束。
递归函数
def d():
    return "123"
def c():
    r = d()
    return r
def b():
    r = c()
    return r
def a():
    r = b()
    print(r)
a()
#123
def func(n):
    n += 1
    if n >=4:
        return 'end'
    return func(n)
r = func(1)
print(r)
#end
#阶乘递归
def func(num):
    if num == 1:
        return 1
    return num*func(num-1)
a = func(7)
print(a)
#5040

实例,通过递归实现二分查找

1 def binary_search(data_list,find_num):
 2     mid_pos = int(len(data_list) /2 ) # 获取中间的索引
 3     mid_val = data_list[mid_pos] # 获取中间的索引对相应元素,也就是值
 4     print(data_list)
 5     if len(data_list) >1: # 递归结束条件,也就是规模绩效
 6         if mid_val > find_num: # 中间的值比要找的值大,说明在中间值左边
 7             print("[%s] should be in left of [%s]" %(find_num,mid_val))
 8             binary_search(data_list[:mid_pos],find_num) # 递归自己,继续查找自己的左边(也就是递归要求里的缩小调用规模)
 9         elif mid_val < find_num: # 中间的值比要找的值大,说明在中间值左边
10             print("[%s] should be in right of [%s]" %(find_num,mid_val))
11             binary_search(data_list[mid_pos + 1:],find_num)
12         else: # 如果既不大于也不小于说明正好等于
13             print("Find ", find_num)
14  
15     else:
16         # 当列表的大小等于1的时候,不在调用自己,结束递归
17         if mid_val == find_num: # 判断最用一个元素是否等于要查找的数
18             print("Find ", find_num)
19         else:
20             print("cannot find [%s] in data_list" %find_num)
21  
22 if __name__ == '__main__':
23     primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103,104]
24     binary_search(primes,5)
25     binary_search(primes,66)

 执行结果

1 [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 104]
 2 [5] should be in left of [47]
 3 [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43]
 4 [5] should be in left of [19]
 5 [2, 3, 5, 7, 11, 13, 17]
 6 [5] should be in left of [7]
 7 [2, 3, 5]
 8 [5] should be in right of [3]
 9 [5]
10 Find  5
11 [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 104]
12 [66] should be in right of [47]
13 [53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 104]
14 [66] should be in left of [79]
15 [53, 59, 61, 67, 71, 73]
16 [66] should be in left of [67]
17 [53, 59, 61]
18 [66] should be in right of [59]
19 [61]
20 cannot find [66] in data_list
复制代码

 logging模块  

很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误、警告等信息输出,python的logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,logging的日志可以分为 debug()info()warning()error() and critical() 5个级别,下面我们看一下怎么用。

最简单用法

>>> import logging
>>> logging.warning("user [Jason] attempted wrong password more than 5 times")
WARNING:root:user [Jason] attempted wrong password more than 5 times

可见,默认情况下python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,
这说明默认的日志级别设置为WARNING(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET)

默认的日志格式为:日志级别:Logger名称:用户输出消息

 看一下这几个日志级别分别代表什么意思

LevelWhen it’s used
DEBUG Detailed information, typically of interest only when diagnosing problems.
INFO Confirmation that things are working as expected.
WARNING An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected.
ERROR Due to a more serious problem, the software has not been able to perform some function.
CRITICAL A serious error, indicating that the program itself may be unable to continue running.

 如果想把日志写到文件里,也很简单

import logging
logging.basicConfig(filename='test.log',level=logging.INFO)
logging.debug('This message should come to log files')
logging.info('come in this')
logging.warning('hey it came out')

 

 其中下面这句中的level=loggin.INFO意思是,把日志纪录级别设置为INFO,也就是说,只有比日志是INFO或比INFO级别更高的日志才会被纪录到文件里,在这个例子, 第一条日志是不会被纪录的,如果希望纪录debug的日志,那把日志级别改成DEBUG就行了。

感觉上面的日志格式忘记加上时间啦,日志不知道时间怎么行呢,下面就来加上!

import logging
logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
logging.warning('is when this event was logged.')
 
#输出
12/12/2010 11:46:36 AM is when this event was logged.

2.灵活配置日志级别,日志格式,输出位置

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S',
                    filename='test.log',
                    filemode='w')
 
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')

 

在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有

filename:   用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。

filemode:   文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。

format:     指定handler使用的日志显示格式。

datefmt:    指定日期时间格式。(datefmt='%a, %d %b %Y %H:%M:%S',%p)

level:      设置rootlogger(后边会讲解具体概念)的日志级别

stream:     用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。

      若同时列出了filename和stream两个参数,则stream参数会被忽略。

format参数中可能用到的格式化串:
%(name)s             Logger的名字
%(levelno)s          数字形式的日志级别
%(levelname)s     文本形式的日志级别
%(pathname)s     调用日志输出函数的模块的完整路径名,可能没有
%(filename)s        调用日志输出函数的模块的文件名
%(module)s          调用日志输出函数的模块名
%(funcName)s     调用日志输出函数的函数名
%(lineno)d           调用日志输出函数的语句所在的代码行
%(created)f          当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d    输出日志信息时的,自Logger创建以 来的毫秒数
%(asctime)s                 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(thread)d                  线程ID。可能没有
%(threadName)s         线程名。可能没有
%(process)d               进程ID。可能没有
%(message)s             用户输出的消息

如果想同时把log打印在屏幕和文件日志里,就需要了解一点复杂的知识 了

The logging library takes a modular approach and offers several categories of components: loggers, handlers, filters, and formatters.

  • Loggers expose the interface that application code directly uses.
  • Handlers send the log records (created by loggers) to the appropriate destination.
  • Filters provide a finer grained facility for determining which log records to output.
  • Formatters specify the layout of log records in the final output.
import logging
 
#create logger
logger = logging.getLogger('TEST-LOG')
logger.setLevel(logging.DEBUG)
 
 
# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
 
# create file handler and set level to warning
fh = logging.FileHandler("access.log")
fh.setLevel(logging.WARNING)
# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
 
# add formatter to ch and fh
ch.setFormatter(formatter)
fh.setFormatter(formatter)
 
# add ch and fh to logger
logger.addHandler(ch)
logger.addHandler(fh)
 
# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')

3.Logger,Handler,Formatter,Filter的概念

logging.basicConfig()(用默认日志格式(Formatter)为日志系统建立一个默认的流处理器(StreamHandler),
设置基础配置(如日志级别等)并加到root logger(根Logger)中)这几个logging模块级别的函数,
另外还有一个模块级别的函数是logging.getLogger([name])(返回一个logger对象,如果没有指定名字将返回root logger)

1).logging库提供了多个组件:Logger、Handler、Filter、Formatter。

Logger       对象提供应用程序可直接使用的接口,
Handler      发送日志到适当的目的地,
Filter          提供了过滤日志信息的方法,
Formatter   指定日志显示格式。

# 创建一个logger
logger = logging.getLogger()
#创建一个带用户名的logger
logger1 = logging.getLogger('Jasonlog')
#设置一个日志级别
logger.setLevel(logging.INFO)
logger1.setLevel(logging.INFO)
#创建一个handler,用于写入日志文件
fh = logging.FileHandler('test.log')
# 再创建一个handler,用于输出到控制台
ch = logging.StreamHandler()
# 定义handler的输出格式formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
# 给logger添加handler
#logger.addFilter(filter)
logger.addHandler(fh)
logger.addHandler(ch)
# 给logger1添加handler
#logger1.addFilter(filter)
logger1.addHandler(fh)
logger1.addHandler(ch)
#给logger添加日志
logger.info('logger info message')
logger1.info('logger1 info message')

 

 json & pickle模块

用于序列化的两个模块

  • json,用于字符串 和 python数据类型间进行转换
  • pickle,用于python特有的类型 和 python的数据类型间进行转换

Json模块提供了四个功能:dumps、dump、loads、load

pickle模块提供了四个功能:dumps、dump、loads、load

# import json
# dic = {'k1':'v1'}
# print(dic,type(dic))
# #将python的基本类型转换为字符串
# result = json.dumps(dic)
# print(result,type(result))
{'k1': 'v1'} <class 'dict'>
{"k1": "v1"} <class 'str'>
s1 = '{"k1":123}'
import json
dic = json.loads(s1) #存入内存中
print(dic,type(dic))
{'k1': 123} <class 'dict'>
import requests
import json
response = requests.get('http://wthrcdn.etouch.cn/weather_mini?city=北京')
response.encoding = 'utf-8'
print(response)
#输出
#<Response [200]>
dic = json.loads(response.text)#**使用双引号
print(dic)
print(type(dic))
#输出
{'desc': 'OK', 'data': {'wendu': '30', 'aqi': '125', 'city': '北京', 'forecast': [{'type': '多云', 'low': '低温 18℃', 'fengli': '微风级', 'date': '5日星期天', 'high': '高温 30℃', 'fengxiang': '无持续风向'}, {'type': '多云', 'low': '低温 20℃', 'fengli': '微风级', 'date': '6日星期一', 'high': '高温 30℃', 'fengxiang': '无持续风向'}, {'type': '雷阵雨', 'low': '低温 16℃', 'fengli': '微风级', 'date': '7日星期二', 'high': '高温 24℃', 'fengxiang': '无持续风向'}, {'type': '晴', 'low': '低温 21℃', 'fengli': '微风级', 'date': '8日星期三', 'high': '高温 31℃', 'fengxiang': '无持续风向'}, {'type': '晴', 'low': '低温 22℃', 'fengli': '微风级', 'date': '9日星期四', 'high': '高温 33℃', 'fengxiang': '无持续风向'}], 'ganmao': '各项气象条件适宜,发生感冒机率较低。但请避免长期处于空调房间中,以防感冒。', 'yesterday': {'fx': '无持续风向', 'type': '阴', 'low': '低温 19℃', 'fl': '微风', 'date': '4日星期六', 'high': '高温 30℃'}}, 'status': 1000}
<class 'dict'>

import json
li = [11,22,33]
json.dump(li,open('db','w'))#序列化
li = json.load(open('db','r'))##将字符产反序列化,读文件
print(type(li),li)
#输出
#<class 'list'> [11, 22, 33]json/pickle
比较json更加适合跨语言,字符串,基本数据类型
class Foo():
    def f1(self):
        print('test')
import json
a = Foo
r = json.loads(a)
print(r)

 TypeError: the JSON object must be str, not 'type'

pickle,python复杂类型序列化,仅适用于python

import pickle
li = [11,22,33]
r = pickle.dumps(li)
print(r)
#b'x80x03]qx00(Kx0bKx16K!e.'
result = pickle.loads(r)
print(result)
#[11, 22, 33]
import pickle
li = [11,22,33]
pickle.dump(li, open('db','wb'))
result = pickle.load(open('db','rb'))
print(result)
#[11, 22, 33]

双层装饰器

User_INFO = {}

def check_login(func):
    def inner(*args,**kwargs):
        if User_INFO.get('is_login',None):
            ret = func(*args, **kwargs)
            return ret
        else:
            print('请登录')

    return inner

def check_admin(func):
    def inner(*args,**kwargs):
        if User_INFO.get('user_type',None) == 2:
            ret = func(*args,**kwargs)
            return ret
        else:
            print("无权限查看")
    return inner
@check_login
@check_admin
def index():
    print("login success")
@check_login
def login():
    User_INFO['is_login'] = 'True'
    print("普通用户登录")

def search():
    print("")
def main():
    while True:
        inp = input("1.登录2.查看3.后台登录")
        if inp == '1':
            User_INFO['is_login'] = True
            login()
        elif inp == '2':
            search()
        elif inp == '3':
            User_INFO['user_type'] = 2
            index()

main()

 常用格式化

字符串格式化
s = "alex %"
print(s)
#alex %

tp1 = "i am %s age %d" %("alex",18)
print(tp1)
##i am alex age 18
tp2 = "i am %(name)s age %(age)d" % {"name":"alex","age":17}
print(tp2)
#i am alex age 17
tp3 = "percent %.2f" % 99.2234234
print(tp3)
#percent 99.22
tp4 = "i am %(pp).2f %%" % {"pp": 123.42556,}
print(tp4)
#i am 123.43 %
tp4 = "i am %.2f %%" % (123.42556,)
print(tp4)
#i am 123.43 %
#format方法

s1 = "adassfdad{0}fads{0}1232{1}".format(123,"Jason")
print(s1)
#adassfdad123fads1231232Jason
s2 = "---{:*^20s}==={:+d}===={:x}".format('alex',12,5)
print(s2)
#---********alex********===+12====5

tp1 = "i am {}, age {}, {}".format("seven", 18, 'alex')
tp2 = "i am {}, age {}, {}".format(*["seven", 18, 'alex'])
print(tp1)
#i am seven, age 18, alex
print(tp2)
#i am seven, age 18, alex
tp3 = "numbers: {:b},{:o},{:d},{:x},{:x}, {:.4%}".format(15,15,15,15,15,34.667)
print(tp3)
#numbers: 1111,17,15,f,f, 3466.7000%
tp3 = "numbers: {:#b},{:#o},{:#d},{:#x},{:#x}, {:.4%}".format(15,15,15,15,15,34.667)
print(tp3)
#numbers: 0b1111,0o17,15,0xf,0xf, 3466.7000%

生成器迭代器

生成器
def func():
    yield 1
    yield 2
    yield 3
ret = func()
for i in ret:
    print(i)
# 1
# 2
# 3
def func():
    print(111)
    yield 1
    print(222)
    yield 2
    print(333)
    yield 3
ret = func()
print(ret)
r1 = ret.__next__()#进入yield函数,湖区yield后面的数据
print(r1)
r2 = ret.__next__()#进入yield函数,湖区yield后面的数据
print(r2)
r3 = ret.__next__()#进入yield函数,湖区yield后面的数据
print(r3)
输出:
#<generator object func at 0x101a82830>
# 111
# 1
# 222
# 2
# 333
# 3
def myrange(arg):
    start = 0
    while True:
        if start > arg:
            return
        yield start
        start += 1
ret = myrange(3)
r = ret.__next__()
print(r)
r = ret.__next__()
print(r)
r = ret.__next__()
print(r)
#
0
1
2

原文地址:https://www.cnblogs.com/jasonwang-2016/p/5587733.html