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

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

1.模块简介html

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

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

2.模块的引入算法

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

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

 

有时候咱们只须要用到模块中的某个函数,只须要引入该函数便可,此时能够经过语句编程

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

例:windows

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

 模块分为三种api

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

#安装模块的几种方式app

(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所指向的文件或者目录的最后修改时间

  二、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

 3、递归

    在函数内部,能够调用其余函数。若是一个函数在内部调用自身自己,这个函数就是递归函数。递归算法对解决一大类问题是十分有效的,它每每使算法的描述简洁并且易于理解。
递归算法解决问题的特色:
(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名称:用户输出消息

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

Level When 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'\x80\x03]q\x00(K\x0bK\x16K!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)
#012
相关文章
相关标签/搜索