Python/Standard Library

维基教科书,自由的教学读本

os模块[编辑]

os模块就是对操作系统进行操作

  • os.remove() 删除文件
  • os.unlink() 删除文件
  • os.rename() 重命名文件
  • os.listdir() 列出指定目录下所有文件
  • os.chdir() 改变当前工作目录
  • os.getcwd() 获取当前文件路径
  • os.mkdir() 新建目录
  • os.rmdir() 删除空目录(删除非空目录, 使用shutil.rmtree())
  • os.makedirs() 创建多级目录
  • os.removedirs() 删除多级目录
  • os.stat(file) 获取文件属性
  • os.chmod(file) 修改文件权限
  • os.utime(file) 修改文件时间戳
  • os.name(file) 获取操作系统标识
  • os.system() 执行操作系统命令
  • os.execvp() 启动一个新进程
  • os.fork() 获取父进程ID,在子进程返回中返回0
  • os.execvp() 执行外部程序脚本(Uinx)
  • os.spawn() 执行外部程序脚本(Windows)
  • os.access(path, mode) 判断文件权限(详细参考cnblogs)
  • os.wait() 暂时未知
  • os.open()
  • os.walk() 生成目录树下的所有文件名
  • os.getenv() 获取系统的环境变量
  • os.putenv() 将一个目录添加到环境变量中(临时增加仅对当前脚本有效)
  • os.exit() 退出终端的命令
  • os.curdir 表示当前文件夹的变量
  • os.pardir 表示上一层文件夹的变量
  • os.name 获取代表操作系统的名称字符串的变量
  • os.sep 获取系统路径间隔符号的变量
  • os.extsep 获取文件名称和后缀之间的间隔符号的变量
  • os.linesep 获取操作系统的换行符号的变量
  • os.environ 用于获取和设置系统环境变量的内置值的字典

os.path模块[编辑]

  • os.path.split(filename) 将文件路径和文件名分割(会将最后一个目录作为文件名而分离)
  • os.path.splitext(filename) 将文件路径和文件扩展名分割成一个元组
  • os.path.dirname(filename) 返回文件路径的目录部分
  • os.path.basename(filename) 返回文件路径的文件名部分
  • os.path.join(dirname,basename) 将文件路径和文件名凑成完整文件路径
  • os.path.abspath(name) 获得绝对路径
  • os.path.splitunc(path) 把路径分割为挂载点和文件名
  • os.path.normpath(path) 规范path字符串形式
  • os.path.exists() 判断文件或目录是否存在
  • os.path.isabs() 如果path是绝对路径,返回True
  • os.path.realpath(path) #返回path的真实路径
  • os.path.relpath(path[, start]) #从start开始计算相对路径
  • os.path.normcase(path) #转换path的大小写和斜杠
  • os.path.isdir() 判断name是不是一个目录,name不是目录就返回false
  • os.path.isfile() 判断name是不是一个文件,不存在返回false
  • os.path.islink() 判断文件是否连接文件,返回boolean
  • os.path.ismount() 指定路径是否存在且为一个挂载点,返回boolean
  • os.path.samefile() 是否相同路径的文件,返回boolean
  • os.path.getatime() 返回最近访问时间 浮点型
  • os.path.getmtime() 返回上一次修改时间 浮点型
  • os.path.getctime() 返回文件创建时间 浮点型
  • os.path.getsize() 返回文件大小 字节单位
  • os.path.commonprefix(list) #返回list(多个路径)中,所有path共有的最长的路径
  • os.path.lexists #路径存在则返回True,路径损坏也返回True
  • os.path.expanduser(path) #把path中包含的”~”和”~user”转换成用户目录
  • os.path.expandvars(path) #根据环境变量的值替换path中包含的”$name”和”${name}”
  • os.path.sameopenfile(fp1, fp2) #判断fp1和fp2是否指向同一文件
  • os.path.samestat(stat1, stat2) #判断stat tuple stat1和stat2是否指向同一个文件
  • os.path.splitdrive(path) #一般用在windows下,返回驱动器名和路径组成的元组
  • os.path.walk(path, visit, arg) #遍历path,给每个path执行一个函数详细见手册
  • os.path.supports_unicode_filenames() 设置是否支持unicode路径名

os.stat()返回的文件属性列表[编辑]

描述os.stat()返回的文件属性列表中各值的意义

  • fileStats = os.stat(path) 获取到的文件属性列表
  • fileStats[stat.ST_MODE] 获取文件的模式
  • fileStats[stat.ST_SIZE] 文件大小
  • fileStats[stat.ST_MTIME] 文件最后修改时间
  • fileStats[stat.ST_ATIME] 文件最后访问时间
  • fileStats[stat.ST_CTIME] 文件创建时间
  • stat.S_ISDIR(fileStats[stat.ST_MODE]) 是否目录
  • stat.S_ISREG(fileStats[stat.ST_MODE]) 是否一般文件
  • stat.S_ISLNK(fileStats[stat.ST_MODE]) 是否连接文件
  • stat.S_ISSOCK(fileStats[stat.ST_MODE]) 是否COCK文件
  • stat.S_ISFIFO(fileStats[stat.ST_MODE]) 是否命名管道
  • stat.S_ISBLK(fileStats[stat.ST_MODE]) 是否块设备
  • stat.S_ISCHR(fileStats[stat.ST_MODE]) 是否字符设置

sys 模块[编辑]

  • sys.argv 命令行参数List,第一个元素是程序本身路径
  • sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
  • sys.modules.keys() 返回所有已经导入的模块列表
  • sys.modules 返回系统导入的模块字段,key是模块名,value是模块
  • sys.exc_info() 获取当前正在处理的异常类,exc_type、exc_value、exc_traceback当前处理的异常详细信息
  • sys.exit(n) 退出程序,正常退出时exit(0)
  • sys.hexversion 获取Python解释程序的版本值,16进制格式如:0x020403F0
  • sys.version 获取Python解释程序的版本信息
  • sys.platform 返回操作系统平台名称
  • sys.stdout 标准输出
  • sys.stdout.write(‘aaa‘) 标准输出内容
  • sys.stdout.writelines() 无换行输出
  • sys.stdin 标准输入
  • sys.stdin.read() 输入一行
  • sys.stderr 错误输出
  • sys.exc_clear() 用来清除当前线程所出现的当前的或最近的错误信息
  • sys.exec_prefix 返回平台独立的python文件安装的位置
  • sys.byteorder 本地字节规则的指示器,big-endian平台的值是‘big‘,little-endian平台的值是‘little‘
  • sys.copyright 记录python版权相关的东西
  • sys.api_version 解释器的C的API版本
  • sys.version_info ‘final‘表示最终,也有‘candidate‘表示候选,表示版本级别,是否有后继的发行
  • sys.getdefaultencoding() 返回当前你所用的默认的字符编码格式
  • sys.getfilesystemencoding() 返回将Unicode文件名转换成系统文件名的编码的名字
  • sys.builtin_module_names Python解释器导入的内建模块列表
  • sys.executable Python解释程序路径
  • sys.getwindowsversion() 获取Windows的版本
  • sys.stdin.readline() 从标准输入读一行,sys.stdout.write(“a”) 屏幕输出a
  • sys.setdefaultencoding(name) 用来设置当前默认的字符编码(详细使用参考文档)
  • sys.displayhook(value) 如果value非空,这个函数会把他输出到sys.stdout(详细使用参考文档)
  • sys.maxint 最大的Int值
  • sys.maxunicode 最大的Unicode值

time模块[编辑]

time模块中时间表现的格式主要有三种:

  • timestamp时间戳,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量
  • struct_time时间元组,共有九个元素组。可用下标索引或者字段名访问。字段tm_zone为时区名字。字段tm_gmtoff为时区与UTC的偏移秒数。
  • format time 格式化时间,已格式化的结构使时间更具可读性。包括自定义格式和固定格式。

获取本地时区

  • time.daylight 是否处于夏令时
  • time.tzname时区名字list
  • time.timezone 时区与UTC的负值秒数
  • time.altzone 夏令时的负值秒数

获取时间或者转换格式的函数

  • time.mktime(timetupleobj) 将datetime元组对象转为时间戳
  • time.time() 当前时间戳
  • time.localtime 由时间戳到结构化时间
  • time.gmtime 由时间戳到结构化时间
  • time.strptime 从字符串时间到结构化时间
  • time.strftime 从结构化时间到字符串时间
  • time.asctime 从结构化时间到字符串时间
  • time.ctime 从时间戳到字符串时间

format time结构化表示:

  • %a 本地(locale)简化星期名称
  • %A 本地完整星期名称
  • %b 本地简化月份名称
  • %B 本地完整月份名称
  • %c 本地相应的日期和时间表示
  • %d 一个月中的第几天(01 - 31)
  • %H 一天中的第几个小时(24小时制,00 - 23)
  • %I 第几个小时(12小时制,01 - 12)
  • %j 一年中的第几天(001 - 366)
  • %m 月份(01 - 12)
  • %M 分钟数(00 - 59)
  • %p 本地am或者pm的相应符
  • %S 秒(01 - 61)
  • %U 一年中的星期数。(00 - 53星期天是一个星期的开始。)第一个星期天之前的所有天数都放在第0周。
  • %w 一个星期中的第几天(0 - 6,0是星期天)
  • %W 和%U基本相同,不同的是%W以星期一为一个星期的开始。
  • %x 本地相应日期
  • %X 本地相应时间
  • %y 去掉世纪的年份(00 - 99)
  • %Y 完整的年份
  • %Z 时区的名字(如果不存在为空字符)
  • %% ‘%’字符

datetime模块[编辑]

datatime模块重新封装了time模块,提供更多接口,提供的类有:date,time,datetime,timedelta,tzinfo。

可表示的年份为1至9999

date类[编辑]

构造函数:datetime.date(year, month, day)

静态方法和字段:

  • date.max、date.min:date对象所能表示的最大、最小日期;
  • date.resolution:date对象表示日期的最小单位。这里是天。
  • date.today():返回一个表示当前本地日期的date对象;
  • date.fromtimestamp(timestamp):根据给定的C语言时间戮,返回一个本地日期的date对象;
  • date.fromisoformat(date_string):参数格式为“YYYY-MM-DD”
  • date.fromisocalendar(year, week, day):从python3.8开始
  • date.fromordinal(ordinal):从公元1年1月1日开始的day数

方法和属性:

d1 = date(2011,06,03)#date对象
d1.year、date.month、date.day:年、月、日;
d1.replace(year, month, day):生成一个新的日期对象,用参数指定的年,月,日代替原有对象中的属性。(原有对象仍保持不变)
d1.timetuple():返回日期对应的time.struct_time对象;等价于time.struct_time((d.year, d.month, d.day, 0, 0, 0, d.weekday(), yday, -1))
d1.weekday():返回weekday,如果是星期日,返回0;如果是星期一,返回1,以此类推;
d1.isoweekday():返回weekday,如果是星期一,返回1;如果是星期二,返回2,以此类推;
d1.isocalendar():返回格式如(year,week,weekday)的元组;
d1.isoformat():返回格式如'YYYY-MM-DD’的字符串;date.__str__()等效于该函数
d1.strftime(fmt):和time模块format相同。 date.__format__(format)等效于该函数
d1.toordinal():返回整型
d1.ctime():等价于time.ctime(time.mktime(d.timetuple()))。如'Wed Dec  4 00:00:00 2002'

time类[编辑]

datetime.time(hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ) 
time.fromisoformat(time_string):如HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]
t1 = datetime.time(10,23,15)#time对象
t1.hour、t1.minute、t1.second、t1.microsecond:时、分、秒、微秒;
t1.tzinfo:时区信息;
t1.replace([ hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ] ):创建一个新的时间对象,用参数指定的时、分、秒、微秒代替原有对象中的属性(原有对象仍保持不变);
t1.isoformat():返回型如"HH:MM:SS"格式的字符串表示;
t1.strftime(fmt):同time模块中的format;

静态方法和字段

time.min、time.max:time类所能表示的最小、最大时间。其中,time.min = time(0, 0, 0, 0), time.max = time(23, 59, 59, 999999);
time.resolution:时间的最小单位,这里是1微秒;

datetime类[编辑]

datetime相当于date和time结合起来。

 datetime.datetime (year, month, day[ , hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ] );其中month和day都从1开始

静态方法和字段

datetime.today():返回一个表示当前本地时间的datetime对象;
datetime.now([tz]):返回一个表示当前本地时间的datetime对象,如果提供了参数tz,则获取tz参数所指时区的本地时间;
datetime.utcnow():返回一个当前utc时间的datetime对象;#格林威治时间
datetime.fromtimestamp(timestamp[, tz]):根据时间戮创建一个datetime对象,参数tz指定时区信息;
datetime.utcfromtimestamp(timestamp):根据时间戮创建一个datetime对象;
datetime.fromordinal(ordinal)
datetime.combine(date, time):根据date和time,创建一个datetime对象;
datetime.fromisoformat(date_string):例如'2011-11-04T00:05:23.283+00:00' 其中T可以替换为任意单个字符
datetime.fromisocalendar(year, week, day)
datetime.strptime(date_string, format):将格式字符串转换为datetime对象;

方法和属性

dt=datetime.now()#datetime对象
dt.year、month、day、hour、minute、second、microsecond、tzinfo:
dt.date():获取date对象;
dt.time():获取time对象;
dt.timetz()
dt.astimezone(tz=None):返回一个新的实例,其时区已经改变。如果参数为空,则使用本地时区。如果tzinfo成员为空,参数为非本地时区,则报错。如果tzinfo成员不为空,则改用参数指定的时区。
dt.replace ([ year[ , month[ , day[ , hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ] ] ] ]):替换各个数据成员
dt.timetuple(): 相当于:time.struct_time((d.year, d.month, d.day,d.hour, d.minute, d.second,d.weekday(), yday, dst))
dt.utctimetuple()
dt.toordinal():从公元1年元旦开始的天数
dt.timestamp():返回浮点数
dt.weekday():星期一为0
dt.isoweekday():星期一为1
dt.isocalendar():返回结果是三元组(年份,第几周,第几天)
dt.isoformat ([ sep] ) 
dt.ctime ():返回一个日期时间的C格式字符串,等效于time.ctime(time.mktime(dt.timetuple()));
dt.strftime (format)

在Include/datetime.h中记录了datetime类的声明实现:

/* Fields are packed into successive bytes, each viewed as unsigned and
 * big-endian, unless otherwise noted:
 *
 * byte offset
 *  0           year     2 bytes, 1-9999
 *  2           month    1 byte, 1-12
 *  3           day      1 byte, 1-31
 *  4           hour     1 byte, 0-23
 *  5           minute   1 byte, 0-59
 *  6           second   1 byte, 0-59
 *  7           usecond  3 bytes, 0-999999
 * 10
 */

...

/* # of bytes for year, month, day, hour, minute, second, and usecond. */
#define _PyDateTime_DATETIME_DATASIZE 10

...

/* The datetime and time types have hashcodes, and an optional tzinfo member,
 * present if and only if hastzinfo is true.
 */
#define _PyTZINFO_HEAD          \
    PyObject_HEAD               \
    Py_hash_t hashcode;         \
    char hastzinfo;             /* boolean flag */

...

/* All datetime objects are of PyDateTime_DateTimeType, but that can be
 * allocated in two ways too, just like for time objects above.  In addition,
 * the plain date type is a base class for datetime, so it must also have
 * a hastzinfo member (although it's unused there).
 */

...

#define _PyDateTime_DATETIMEHEAD        \
    _PyTZINFO_HEAD                      \
    unsigned char data[_PyDateTime_DATETIME_DATASIZE];

typedef struct
{
    _PyDateTime_DATETIMEHEAD
} _PyDateTime_BaseDateTime;     /* hastzinfo false */

typedef struct
{
    _PyDateTime_DATETIMEHEAD
    unsigned char fold;
    PyObject *tzinfo;
} PyDateTime_DateTime;          /* hastzinfo true */

datetime对象的尺寸为48字节,其成员布局为:

  • 8 字节引用计数
  • 8字节类型指针
  • 8 字节缓存哈希
  • 1 字节“hastzinfo”标志
  • 10 字节手动打包 unsigned char[10] 包含日期时间数据
  • 1 字节“折叠”标志 ( DST-related )
  • 4 字节填充,对齐 tzinfo 指针
  • 8 字节 tzinfo 指针

timedelta类[编辑]

时间加减,使用timedelta可以很方便的在日期上做天days,小时hour,分钟,秒,毫秒,微妙的时间计算,如果要计算月份则需要另外的办法。

datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0):构造函数,所有参数可选,可为负值,可为浮点数。内部表示归一化为天、秒、微妙的组合。
dt = datetime.now()
#日期减一天
dt1 = dt + timedelta(days=-1)#昨天
dt2 = dt - timedelta(days=1)#昨天
dt3 = dt + timedelta(days=1)#明天
delta_obj = dt3-dt
print type(delta_obj),delta_obj#<type 'datetime.timedelta'> 1 day, 0:00:00
print delta_obj.days ,delta_obj.total_seconds()#1 86400.0

tzinfo时区类[编辑]

tzinfo是关于时区信息的类。tzinfo是一个抽象类,所以不能直接被实例化。

 class UTC(tzinfo):
    """UTC"""
    def __init__(self,offset = 0):
        self._offset = offset

    def utcoffset(self, dt):
        return timedelta(hours=self._offset)

    def tzname(self, dt):
        return "UTC +%s" % self._offset

    def dst(self, dt): //夏时制
        return timedelta(hours=0)

 #北京时间
 beijing = datetime(2011,11,11,0,0,0,tzinfo = UTC(8))
 print "beijing time:",beijing
 #曼谷时间
 bangkok = datetime(2011,11,11,0,0,0,tzinfo = UTC(7))
 print "bangkok time",bangkok
 #北京时间转成曼谷时间
 print "beijing-time to bangkok-time:",beijing.astimezone(UTC(7))

 #计算时间差时也会考虑时区的问题
 timespan = beijing - bangkok
 print "时差:",timespan

timezone[编辑]

timezone是tzinfo的子类。构造为datetime.timezone(datetime.timedelta(hours=8), name="Asina/Shanghai")

hashlib加密[编辑]

hashlib主要提供字符加密功能,将md5和sha模块整合到了一起,支持md5,sha1, sha224, sha256, sha384, sha512等算法。注意:hashlib 加密的字符串类型为二进制编码,直接加密字符串会报错:TypeError: Unicode-objects must be encoded before hashing

import hashlib
# ######## md5 ########
string = "beyongjie"
md5 = hashlib.md5()
md5.update(string.encode('utf-8'))     #注意转码
res = md5.hexdigest()
print("md5加密结果:",res)

# ######## sha1 ########
sha1 = hashlib.sha1()
sha1.update(string.encode('utf-8'))
res = sha1.hexdigest()
print("sha1加密结果:",res)

# ######## sha256 ########
sha256 = hashlib.sha256()
sha256.update(string.encode('utf-8'))
res = sha256.hexdigest()
print("sha256加密结果:",res)


# ######## sha384 ########
sha384 = hashlib.sha384()
sha384.update(string.encode('utf-8'))
res = sha384.hexdigest()
print("sha384加密结果:",res)

# ######## sha512 ########
sha512= hashlib.sha512()
sha512.update(string.encode('utf-8'))
res = sha512.hexdigest()
print("sha512加密结果:",res)

常用方法

  • hash.update(arg) 更新哈希对象以字符串参数, 注意:如果同一个hash对象重复调用该方法,则m.update(a); m.update(b) 等效于 m.update(a+b),看下面例子
  • hash.digest() 返回摘要,作为二进制数据字符串值,
  • hash.hexdigest() 返回摘要,作为十六进制数据字符串值,
  • hash.copy() 复制

以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。所以,有必要对加密算法中添加自定义key再来做加密。

low = hashlib.md5()
low.update('ab'.encode('utf-8'))
res = low.hexdigest()
print("普通加密:",res)

high = hashlib.md5(b'beyondjie')
high.update('ab'.encode('utf-8'))
res = high.hexdigest()
print("采用key加密:",res)

在各大开放平台大的API接口过程中,无一例外都会用到计算签名值(sig值)。而在各种计算签名的方法中,经常被采用的就是HMAC-SHA1:HMAC,散列消息鉴别码,基于密钥的Hash算法认证协议。实现原理为:利用已经公开的Hash函数和私有的密钥,来生成固定长度的消息鉴别码;SHA1、MD5等Hash算法是比较常用的不可逆Hash签名计算方法;BASE64,将任意序列的8字节字符转换为人眼无法直接识别的符号编码的一种方法

             import hmac
             import hashlib
             import base64
             hmac.new(Token,data,hashlib.sha1).digest().encode('base64').rstrip()
  • Token:即接口的key
  • data:要加密的数据

logging模块[编辑]

logging模块是Python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级、日志保存路径、日志文件回滚等;相比print,具备如下优点:

  • 可以通过设置不同的日志等级,在release版本中只输出重要信息,而不必显示大量的调试信息;
  • print将所有信息都输出到标准输出中,严重影响开发者从标准输出中查看其它数据;logging则可以由开发者决定将信息输出到什么地方,以及怎么输出;

logging模块中的类[编辑]

在Python的lib目录下的logging子目录下,有3个py文件,组成logging的主干的几个基础类都在__init__.py中:

#主干代码
/usr/lib/python2.7/logging/__init__.py
#扩展的handler和config
/usr/lib/pyhon2.7/logging/config.py
/usr/lib/python2.7/loging/handlers.py
类名字 方法 说明
LogRecord 构造函数传入所有信息
getMessage 返回具体内容
每行记下的日志信息对应一条LogRecord,包含所有信息,如时间、代码行号等,组成一个字典
Formatter
  • __init__(fmt=None, datefmt=None, style='%')
用于把一条日志的字典中的信息,格式化输出为文本。
Logger
  • Logger.setLevel()
  • Logger.addHandler() 和 Logger.removeHandler()
  • Logger.addFilter() 和 Logger.removeFilter()
  • Logger.debug(), Logger.info(), Logger.warning(), Logger.error(), Logger.critical()
  • Logger.exception()
  • Logger.log()
  1. 发送log信息
  2. 过滤log信息
  3. 把log信息传给handler

getLogger()返回一个loggger,其参数指出在一个继承结构中的哪一个logger。后代logger会把消息传播给祖先logger。

Handler
  • setLevel()设定handler能处理的消息级别
  • setFormatter()
  • addFilter() 和 removeFilter()
作为基类,应该派生自己的类使用
示例 示例 示例
示例 示例 示例
示例 示例 示例
示例 示例 示例


控制台输出日志[编辑]

import logging
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='myapp.log',
                filemode='w')
logger = logging.getLogger(__name__)

logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
logger.info("Finish")

运行时,控制台输出:

2016-10-09 19:11:19,434 - __main__ - INFO - Start print log
2016-10-09 19:11:19,434 - __main__ - WARNING - Something maybe fail.
2016-10-09 19:11:19,434 - __main__ - INFO - Finish

logging中可以选择很多消息级别,如debug、info、warning、error以及critical。通过赋予logger或者handler不同的级别,开发者就可以只输出错误信息到特定的记录文件,或者在调试时只记录调试信息。例如,我们将logger的级别改为DEBUG,再观察一下输出结果:

logging.basicConfig(level = logging.DEBUG,format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s')

控制台输出了debug的信息:

2016-10-09 19:12:08,289 - __main__ - INFO - Start print log
2016-10-09 19:12:08,289 - __main__ - DEBUG - Do something
2016-10-09 19:12:08,289 - __main__ - WARNING - Something maybe fail.
2016-10-09 19:12:08,289 - __main__ - INFO - Finish

logging.basicConfig函数各参数:

  • filename:指定日志文件名;
  • filemode:和file函数意义相同,指定日志文件的打开模式,'w'或者'a';
  • format:指定输出的格式和内容,format可以输出很多有用的信息,
    • %(levelno)s:打印日志级别的数值
    • %(levelname)s:打印日志级别的名称
    • %(pathname)s:打印当前执行程序的路径,其实就是sys.argv[0]
    • %(filename)s:打印当前执行程序名
    • %(funcName)s:打印日志的当前函数
    • %(lineno)d:打印日志的当前行号
    • %(asctime)s:打印日志的时间
    • %(thread)d:打印线程ID
    • %(threadName)s:打印线程名称
    • %(process)d:打印进程ID
    • %(message)s:打印日志信息
  • datefmt:指定时间格式,同time.strftime();
  • level:设置日志级别,默认为logging.WARNNING; CRITICAL = 50 ERROR = 40 WARNING = 30 INFO 20 DEBUG = 10 NOTEST = 0
  • stream:指定将日志的输出流,可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,当stream和filename同时指定时,stream被忽略;
   %(name)s            Name of the logger (logging channel)
   %(levelno)s         Numeric logging level for the message (DEBUG, INFO,
                       WARNING, ERROR, CRITICAL)
   %(levelname)s       Text logging level for the message ("DEBUG", "INFO",
                       "WARNING", "ERROR", "CRITICAL")
   %(pathname)s        Full pathname of the source file where the logging
                       call was issued (if available)
   %(filename)s        Filename portion of pathname
   %(module)s          Module (name portion of filename)
   %(lineno)d          Source line number where the logging call was issued
                       (if available)
   %(funcName)s        Function name
   %(created)f         Time when the LogRecord was created (time.time()
                       return value)
   %(asctime)s         Textual time when the LogRecord was created
   %(msecs)d           Millisecond portion of the creation time
   %(relativeCreated)d Time in milliseconds when the LogRecord was created,
                       relative to the time the logging module was loaded
                       (typically at application startup time)
   %(thread)d          Thread ID (if available)
   %(threadName)s      Thread name (if available)
   %(process)d         Process ID (if available)
   %(message)s         The result of record.getMessage(), computed just as
                       the record is emitted

将日志写入到文件[编辑]

设置logging,创建一个FileHandler,并对输出消息的格式进行设置,将其添加到logger,然后将日志写入到指定的文件中

import logging
logger = logging.getLogger(__name__)
logger.setLevel(level = logging.INFO)
handler = logging.FileHandler("log.txt")
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)

logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
logger.info("Finish")

将日志同时输出到屏幕和日志文件[编辑]

logger中添加StreamHandler,可以将日志输出到屏幕上

import logging
logger = logging.getLogger(__name__)
logger.setLevel(level = logging.INFO)
handler = logging.FileHandler("log.txt")
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)

console = logging.StreamHandler()
console.setLevel(logging.INFO)

logger.addHandler(handler)
logger.addHandler(console)

logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
logger.info("Finish")

可以发现,logging有一个日志处理的主对象,其他处理方式都是通过addHandler添加进去,logging中包含的handler主要有如下几种,

  • handler名称 位置 作用
  • StreamHandler:logging.StreamHandler;日志输出到流,可以是sys.stderr,sys.stdout或者文件
  • FileHandler:logging.FileHandler;日志输出到文件
  • BaseRotatingHandler:logging.handlers.BaseRotatingHandler;基本的日志回滚方式
  • RotatingHandler:logging.handlers.RotatingHandler;日志回滚方式,支持日志文件最大数量和日志文件回滚
  • TimeRotatingHandler:logging.handlers.TimeRotatingHandler;日志回滚方式,在一定时间区域内回滚日志文件
  • SocketHandler:logging.handlers.SocketHandler;远程输出日志到TCP/IP sockets
  • DatagramHandler:logging.handlers.DatagramHandler;远程输出日志到UDP sockets
  • SMTPHandler:logging.handlers.SMTPHandler;远程输出日志到邮件地址
  • SysLogHandler:logging.handlers.SysLogHandler;日志输出到syslog
  • NTEventLogHandler:logging.handlers.NTEventLogHandler;远程输出日志到Windows NT/2000/XP的事件日志
  • MemoryHandler:logging.handlers.MemoryHandler;日志输出到内存中的指定buffer
  • HTTPHandler:logging.handlers.HTTPHandler;通过"GET"或者"POST"远程输出到HTTP服务器

日志回滚[编辑]

使用RotatingFileHandler,可以实现日志回滚,

import logging
from logging.handlers import RotatingFileHandler
logger = logging.getLogger(__name__)
logger.setLevel(level = logging.INFO)
#定义一个RotatingFileHandler,最多备份3个日志文件,每个日志文件最大1K
rHandler = RotatingFileHandler("log.txt",maxBytes = 1*1024,backupCount = 3)
rHandler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
rHandler.setFormatter(formatter)

console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setFormatter(formatter)

logger.addHandler(rHandler)
logger.addHandler(console)

logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
logger.info("Finish")

可以在工程目录中看到,备份的日志文件:

2016/10/09  19:36               732 log.txt
2016/10/09  19:36               967 log.txt.1
2016/10/09  19:36               985 log.txt.2
2016/10/09  19:36               976 log.txt.3

设置消息的等级[编辑]

可以设置不同的日志等级,用于控制日志的输出,

  • 日志等级:使用范围
  • FATAL:致命错误
  • CRITICAL:特别糟糕的事情,如内存耗尽、磁盘空间为空,一般很少使用
  • ERROR:发生错误时,如IO操作失败或者连接问题
  • WARNING:发生很重要的事件,但是并不是错误时,如用户登录密码错误
  • INFO:处理请求或者状态变化等日常事务
  • DEBUG:调试过程中使用DEBUG等级,如算法中每个循环的中间状态

捕获traceback[编辑]

Python中的traceback模块被用于跟踪异常返回信息,可以在logging中记录下traceback,

import logging
logger = logging.getLogger(__name__)
logger.setLevel(level = logging.INFO)
handler = logging.FileHandler("log.txt")
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)

console = logging.StreamHandler()
console.setLevel(logging.INFO)

logger.addHandler(handler)
logger.addHandler(console)

logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
try:
    open("sklearn.txt","rb")
except (SystemExit,KeyboardInterrupt):
    raise
except Exception:
    logger.error("Faild to open sklearn.txt from logger.error",exc_info = True)

logger.info("Finish")

控制台和日志文件log.txt中输出:

Start print log
Something maybe fail.
Faild to open sklearn.txt from logger.error
Traceback (most recent call last):
  File "G:\zhb7627\Code\Eclipse WorkSpace\PythonTest\test.py", line 23, in <module>
    open("sklearn.txt","rb")
IOError: [Errno 2] No such file or directory: 'sklearn.txt'
Finish

也可以使用logger.exception(msg,_args),它等价于logger.error(msg,exc_info = True,_args),将

logger.error("Faild to open sklearn.txt from logger.error",exc_info = True)

替换为,

logger.exception("Failed to open sklearn.txt from logger.exception")

控制台和日志文件log.txt中输出,

Start print log
Something maybe fail.
Failed to open sklearn.txt from logger.exception
Traceback (most recent call last):
  File "G:\zhb7627\Code\Eclipse WorkSpace\PythonTest\test.py", line 23, in <module>
    open("sklearn.txt","rb")
IOError: [Errno 2] No such file or directory: 'sklearn.txt'
Finish

多模块使用logging[编辑]

#主模块mainModule.py
import logging
import subModule
logger = logging.getLogger("mainModule")
logger.setLevel(level = logging.INFO)
handler = logging.FileHandler("log.txt")
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)

console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setFormatter(formatter)

logger.addHandler(handler)
logger.addHandler(console)


logger.info("creating an instance of subModule.subModuleClass")
a = subModule.SubModuleClass()
logger.info("calling subModule.subModuleClass.doSomething")
a.doSomething()
logger.info("done with  subModule.subModuleClass.doSomething")
logger.info("calling subModule.some_function")
subModule.som_function()
logger.info("done with subModule.some_function")
#子模块subModule.py,
import logging

module_logger = logging.getLogger("mainModule.sub")
class SubModuleClass(object):
    def __init__(self):
        self.logger = logging.getLogger("mainModule.sub.module")
        self.logger.info("creating an instance in SubModuleClass")
    def doSomething(self):
        self.logger.info("do something in SubModule")
        a = []
        a.append(1)
        self.logger.debug("list a = " + str(a))
        self.logger.info("finish something in SubModuleClass")

def som_function():
    module_logger.info("call function some_function")

执行之后,在控制和日志文件log.txt中输出,

2016-10-09 20:25:42,276 - mainModule - INFO - creating an instance of subModule.subModuleClass
2016-10-09 20:25:42,279 - mainModule.sub.module - INFO - creating an instance in SubModuleClass
2016-10-09 20:25:42,279 - mainModule - INFO - calling subModule.subModuleClass.doSomething
2016-10-09 20:25:42,279 - mainModule.sub.module - INFO - do something in SubModule
2016-10-09 20:25:42,279 - mainModule.sub.module - INFO - finish something in SubModuleClass
2016-10-09 20:25:42,279 - mainModule - INFO - done with  subModule.subModuleClass.doSomething
2016-10-09 20:25:42,279 - mainModule - INFO - calling subModule.some_function
2016-10-09 20:25:42,279 - mainModule.sub - INFO - call function some_function
2016-10-09 20:25:42,279 - mainModule - INFO - done with subModule.some_function

首先在主模块定义了logger'mainModule',并对它进行了配置,就可以在解释器进程里面的其他地方通过getLogger('mainModule')得到的对象都是一样的,不需要重新配置,可以直接使用。定义的该logger的子logger,都可以共享父logger的定义和配置,所谓的父子logger是通过命名来识别,任意以'mainModule'开头的logger都是它的子logger,例如'mainModule.sub'。

实际开发一个application,首先可以通过logging配置文件编写好这个application所对应的配置,可以生成一个根logger,如'PythonAPP',然后在主函数中通过fileConfig加载logging配置,接着在application的其他地方、不同的模块中,可以使用根logger的子logger,如'PythonAPP.Core','PythonAPP.Web'来进行log,而不需要反复的定义和配置各个模块的logger。

通过JSON文件配置logging模块[编辑]

尽管可以在Python代码中配置logging,但是这样并不够灵活,最好的方法是使用一个配置文件来配置。在Python 2.7及以后的版本中,可以从字典中加载logging配置,也就意味着可以通过JSON或者YAML文件加载日志的配置。

JSON配置文件:

{
    "version":1,
    "disable_existing_loggers":false,
    "formatters":{
        "simple":{
            "format":"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
        }
    },
    "handlers":{
        "console":{
            "class":"logging.StreamHandler",
            "level":"DEBUG",
            "formatter":"simple",
            "stream":"ext://sys.stdout"
        },
        "info_file_handler":{
            "class":"logging.handlers.RotatingFileHandler",
            "level":"INFO",
            "formatter":"simple",
            "filename":"info.log",
            "maxBytes":"10485760",
            "backupCount":20,
            "encoding":"utf8"
        },
        "error_file_handler":{
            "class":"logging.handlers.RotatingFileHandler",
            "level":"ERROR",
            "formatter":"simple",
            "filename":"errors.log",
            "maxBytes":10485760,
            "backupCount":20,
            "encoding":"utf8"
        }
    },
    "loggers":{
        "my_module":{
            "level":"ERROR",
            "handlers":["info_file_handler"],
            "propagate":"no"
        }
    },
    "root":{
        "level":"INFO",
        "handlers":["console","info_file_handler","error_file_handler"]
    }
}

通过JSON加载配置文件,然后通过logging.dictConfig配置logging,

import json
import logging.config
import os

def setup_logging(default_path = "logging.json",default_level = logging.INFO,env_key = "LOG_CFG"):
    path = default_path
    value = os.getenv(env_key,None)
    if value:
        path = value
    if os.path.exists(path):
        with open(path,"r") as f:
            config = json.load(f)
            logging.config.dictConfig(config)
    else:
        logging.basicConfig(level = default_level)

def func():
    logging.info("start func")

    logging.info("exec func")

    logging.info("end func")

if __name__ == "__main__":
    setup_logging(default_path = "logging.json")
    func()

通过YAML文件配置logging模块[编辑]

通过YAML文件进行配置,比JSON看起来更加简介明了

version: 1
disable_existing_loggers: False
formatters:
        simple:
            format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
handlers:
    console:
            class: logging.StreamHandler
            level: DEBUG
            formatter: simple
            stream: ext://sys.stdout
    info_file_handler:
            class: logging.handlers.RotatingFileHandler
            level: INFO
            formatter: simple
            filename: info.log
            maxBytes: 10485760
            backupCount: 20
            encoding: utf8
    error_file_handler:
            class: logging.handlers.RotatingFileHandler
            level: ERROR
            formatter: simple
            filename: errors.log
            maxBytes: 10485760
            backupCount: 20
            encoding: utf8
loggers:
    my_module:
            level: ERROR
            handlers: [info_file_handler]
            propagate: no
root:
    level: INFO
    handlers: [console,info_file_handler,error_file_handler]

通过YAML加载配置文件,然后通过logging.dictConfig配置logging,

import yaml
import logging.config
import os

def setup_logging(default_path = "logging.yaml",default_level = logging.INFO,env_key = "LOG_CFG"):
    path = default_path
    value = os.getenv(env_key,None)
    if value:
        path = value
    if os.path.exists(path):
        with open(path,"r") as f:
            config = yaml.load(f)
            logging.config.dictConfig(config)
    else:
        logging.basicConfig(level = default_level)

def func():
    logging.info("start func")

    logging.info("exec func")

    logging.info("end func")

if __name__ == "__main__":
    setup_logging(default_path = "logging.yaml")
    func()

subprocess模块[编辑]

subprocess是Python 2.4中新增的一个模块,它允许生成新的进程,连接到它们的 input/output/error 管道,并获取它们的返回(状态)码。这个模块的目的在于替换几个旧的模块和方法,如:

   os.system
   os.spawn*
  • 使用的Python 2.4以上,但是是Python 3.5以下的版本,Python官方给出的建议是使用subprocess.call()函数。Python 2.5中新增了一个subprocess.check_call()函数,Python 2.7中新增了一个subprocess.check_output()函数,这两个函数也可以按照需求进行使用。
  • 使用的是Python 3.5及以上的版本(目前应该还很少),Python官方给出的建议是尽量使用subprocess.run()函数。
  • 当subprocess.call()、subprocess.check_call()、subprocess.check_output()和subprocess.run()这些高级函数无法满足需求时,我们可以使用subprocess.Popen类来实现我们需要的复杂功能。

subprocess模块中的常用函数[编辑]

  • 函数 描述
  • subprocess.run() Python 3.5中新增的函数。执行指定的命令,等待命令执行完成后返回一个包含执行结果的CompletedProcess类的实例。
  • subprocess.call() 执行指定的命令,返回命令执行状态,其功能类似于os.system(cmd)。
  • subprocess.check_call() Python 2.5中新增的函数。 执行指定的命令,如果执行成功则返回状态码,否则抛出异常。其功能等价于subprocess.run(..., check=True)。
  • subprocess.check_output() Python 2.7中新增的的函数。执行指定的命令,如果执行状态码为0则返回命令执行结果,否则抛出异常。
  • subprocess.getoutput(cmd) 接收字符串格式的命令,执行命令并返回执行结果,其功能类似于os.popen(cmd).read()和commands.getoutput(cmd)。
  • subprocess.getstatusoutput(cmd) 执行cmd命令,返回一个元组(命令执行状态, 命令执行结果输出),其功能类似于commands.getstatusoutput()。

说明:

  • 在Python 3.5之后的版本中,官方文档中提倡通过subprocess.run()函数替代其他函数来使用subproccess模块的功能;
  • 在Python 3.5之前的版本中,我们可以通过subprocess.call(),subprocess.getoutput()等上面列出的其他函数来使用subprocess模块的功能;
  • subprocess.run()、subprocess.call()、subprocess.check_call()和subprocess.check_output()都是通过对subprocess.Popen的封装来实现的高级函数,因此如果我们需要更复杂功能时,可以通过subprocess.Popen来完成。
  • subprocess.getoutput()和subprocess.getstatusoutput()函数是来自Python 2.x的commands模块的两个遗留函数。它们隐式的调用系统shell,并且不保证其他函数所具有的安全性和异常处理的一致性。另外,它们从Python 3.3.4开始才支持Windows平台。

参数说明:

  • args: 要执行的shell命令,默认应该是一个字符串序列,如['df', '-Th']或('df', '-Th'),也可以是一个字符串,如'df -Th',但是此时需要把shell参数的值置为True。
  • shell: 如果shell为True,那么指定的命令将通过shell执行。如果我们需要访问某些shell的特性,如管道、文件名通配符、环境变量扩展功能,这将是非常有用的。当然,python本身也提供了许多类似shell的特性的实现,如glob、fnmatch、os.walk()、os.path.expandvars()、os.expanduser()和shutil等。
  • check: 如果check参数的值是True,且执行命令的进程以非0状态码退出,则会抛出一个CalledProcessError的异常,且该异常对象会包含 参数、退出状态码、以及stdout和stderr(如果它们有被捕获的话)。

stdout, stderr:

  • run()函数默认不会捕获命令执行结果的正常输出和错误输出,如果我们向获取这些内容需要传递subprocess.PIPE,然后可以通过返回的CompletedProcess类实例的stdout和stderr属性或捕获相应的内容;
  • call()和check_call()函数返回的是命令执行的状态码,而不是CompletedProcess类实例,所以对于它们而言,stdout和stderr不适合赋值为subprocess.PIPE;
  • check_output()函数默认就会返回命令执行结果,所以不用设置stdout的值,如果我们希望在结果中捕获错误信息,可以执行stderr=subprocess.STDOUT。
  • input: 该参数是传递给Popen.communicate(),通常该参数的值必须是一个字节序列,如果universal_newlines=True,则其值应该是一个字符串。
  • universal_newlines: 该参数影响的是输入与输出的数据格式,比如它的值默认为False,此时stdout和stderr的输出是字节序列;当该参数的值设置为True时,stdout和stderr的输出是字符串。

subprocess.CompletedProcess类[编辑]

subprocess.run()函数是Python3.5中新增的一个高级函数,其返回值是一个subprocess.CompletedPorcess类的实例,因此,subprocess.completedPorcess类也是Python 3.5中才存在的。它表示的是一个已结束进程的状态信息,它所包含的属性如下:

  • args: 用于加载该进程的参数,这可能是一个列表或一个字符串
  • returncode: 子进程的退出状态码。通常情况下,退出状态码为0则表示进程成功运行了;一个负值-N表示这个子进程被信号N终止了
  • stdout: 从子进程捕获的stdout。这通常是一个字节序列,如果run()函数被调用时指定universal_newlines=True,则该属性值是一个字符串。如果run()函数被调用时指定stderr=subprocess.STDOUT,那么stdout和stderr将会被整合到这一个属性中,且stderr将会为None
  • stderr: 从子进程捕获的stderr。它的值与stdout一样,是一个字节序列或一个字符串。如果stderr灭有被捕获的话,它的值就为None
  • check_returncode(): 如果returncode是一个非0值,则该方法会抛出一个CalledProcessError异常。

subprocess.Popen[编辑]

该类用于在一个新的进程中执行一个子程序。前面我们提到过,上面介绍的这些函数都是基于subprocess.Popen类实现的,通过使用这些被封装后的高级函数可以很方面的完成一些常见的需求。由于subprocess模块底层的进程创建和管理是由Popen类来处理的,因此,当我们无法通过上面哪些高级函数来实现一些不太常见的功能时就可以通过subprocess.Popen类提供的灵活的api来完成。

subprocess.Popen的构造函数

class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, 
   preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False,
   startup_info=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=())

参数说明:

  • args: 要执行的shell命令,可以是字符串,也可以是命令各个参数组成的序列。当该参数的值是一个字符串时,该命令的解释过程是与平台相关的,因此通常建议将args参数作为一个序列传递。
  • bufsize: 指定缓存策略,0表示不缓冲,1表示行缓冲,其他大于1的数字表示缓冲区大小,负数 表示使用系统默认缓冲策略。
  • stdin, stdout, stderr: 分别表示程序标准输入、输出、错误句柄。
  • preexec_fn: 用于指定一个将在子进程运行之前被调用的可执行对象,只在Unix平台下有效。
  • close_fds: 如果该参数的值为True,则除了0,1和2之外的所有文件描述符都将会在子进程执行之前被关闭。
  • shell: 该参数用于标识是否使用shell作为要执行的程序,如果shell值为True,则建议将args参数作为一个字符串传递而不要作为一个序列传递。
  • cwd: 如果该参数值不是None,则该函数将会在执行这个子进程之前改变当前工作目录。
  • env: 用于指定子进程的环境变量,如果env=None,那么子进程的环境变量将从父进程中继承。如果env!=None,它的值必须是一个映射对象。
  • universal_newlines: 如果该参数值为True,则该文件对象的stdin,stdout和stderr将会作为文本流被打开,否则他们将会被作为二进制流被打开。
  • startupinfo和creationflags: 这两个参数只在Windows下有效,它们将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如主窗口的外观,进程优先级等。

subprocess.Popen类的实例可调用的方法

  • 方法 描述
  • Popen.poll() 用于检查子进程(命令)是否已经执行结束,没结束返回None,结束后返回状态码。
  • Popen.wait(timeout=None) 等待子进程结束,并返回状态码;如果在timeout指定的秒数之后进程还没有结束,将会抛出一个TimeoutExpired异常。
  • Popen.communicate(input=None, timeout=None) 该方法可用来与进程进行交互,比如发送数据到stdin,从stdout和stderr读取数据,直到到达文件末尾。
  • Popen.send_signal(signal) 发送指定的信号给这个子进程。
  • Popen.terminate() 停止该子进程。
  • Popen.kill() 杀死该子进程。

关于communicate()方法的说明:

  • 该方法中的可选参数 input 应该是将被发送给子进程的数据,或者如没有数据发送给子进程,该参数应该是None。input参数的数据类型必须是字节串,如果universal_newlines参数值为True,则input参数的数据类型必须是字符串。
  • 该方法返回一个元组(stdout_data, stderr_data),这些数据将会是字节穿或字符串(如果universal_newlines的值为True)。
  • 如果在timeout指定的秒数后该进程还没有结束,将会抛出一个TimeoutExpired异常。捕获这个异常,然后重新尝试通信不会丢失任何输出的数据。但是超时之后子进程并没有被杀死,为了合理的清除相应的内容,一个好的应用应该手动杀死这个子进程来结束通信。
  • 需要注意的是,这里读取的数据是缓冲在内存中的,所以,如果数据大小非常大或者是无限的,就不应该使用这个方法。

json[编辑]

JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。JSON的数据格式其实就是python里面的字典格式,里面可以包含方括号括起来的数组,也就是python里面的列表。在python中,有专门处理json格式的模块—— json 和 picle模块。json模块和pickle模块都有 dumps、dump、loads、load四种方法,而且用法一样。json模块序列化出来的是通用格式,就是普通的字符串;picle模块序列化出来的只有python可以认识,其他编程语言不认识的,表现为乱码。picle可以序列化函数,但是其他文件想用该函数,在该文件中需要有该文件的定义(定义和参数必须相同,内容可以不同)。

  • dumps只完成了序列化为str,
  • dump必须传文件描述符,将序列化的str保存到文件中
  • loads 只完成了反序列化,
  • load 只接收文件描述符,完成了读取文件和反序列化

python对象(obj) 与json对象的对应关系表:

   +-------------------+---------------+
   | Python            | JSON          |
   +===================+===============+
   | dict              | object        |
   +-------------------+---------------+
   | list, tuple       | array         |
   +-------------------+---------------+
   | str               | string        |
   +-------------------+---------------+
   | int, float        | number        |
   +-------------------+---------------+
   | True              | true          |
   +-------------------+---------------+
   | False             | false         |
   +-------------------+---------------+
   | None              | null          |
   +-------------------+---------------+

configparser[编辑]

configparser 是 Python 标准库中用来解析配置文件的模块,并且内置方法和字典非常接近。Python2.x 中名为 ConfigParser,3.x 已更名小写,并加入了一些新功能。configparser 默认支持=与:两种分隔key/value的分隔符。

>>> import configparser
>>> config = configparser.ConfigParser()    # 首先需要初始化实例 注意大小写
>>> config.read("config.ini")   # 读取配置文件 配置文件的路径
["config.ini"]
>>> parser = configparser.ConfigParser() #或者可以直接读字典
>>> parser.read_dict({'section1': {'key1': 'value1',
...                                'key2': 'value2',
...                                'key3': 'value3'},
...                   'section2': {'keyA': 'valueA',
...                                'keyB': 'valueB',
...                                'keyC': 'valueC'},
...                   'section3': {'foo': 'x',
...                                'bar': 'y',
...                                'baz': 'z'}
... })

>>> config.sections() #获取所有 sections
['bitbucket.org', 'topsecret.com']    # 注意会过滤掉[DEFAULT]
>>> config.items('topsecret.com') #获取指定 section 的 keys & values
>>>> [('port', '50022'), ('forwardx11', 'no')]    # 注意items()返回的字符串会全变成小写
>>> config.options('topsecret.com') #获取指定 section 的 keys
['Port', 'ForwardX11']
>>> for option in config['topsecret.com']:
...     print(option)
Port
ForwardX11
>>> config['bitbucket.org']['User'] #获取指定 key 的 value
'Tom'
>>> config.get('bitbucket.org', 'User')
'Tom'
>>> config.getint('topsecret.com', 'Port')
50022
>>> 'DEFAULT' in config #检查
True
>>> 'test' in config['section_test']
False
>>> 'Tom' in config['bitbucket.org']['User']
True
>>> config.has_section('bitbucket.org')
True
>>> config.has_option('section_test', 'test')
False
>>> config.add_section('Section_1') #添加
>>> config.set('Section_1', 'key_1', 'value_1')    # 注意键值是用set()方法
>>> config.write(open('config.ini', 'w'))    # 一定要写入才生效
>>> config.remove_option('Section_1', 'key_1')#删除
True
>>> config.remove_section('Section_1')
True
>>> config.clear()  # 清空除[DEFAULT]之外所有内容
>>> config.write(open('config.ini', 'w'))

[DEFAULT] 一般包含 ini 格式配置文件的默认项,所以 configparser 部分方法会自动跳过这个 section 。 前面已经提到 sections() 是获取不到的,还有删除方法对 [DEFAULT] 也无效:但指定删除和修改 [DEFAULT] 里的 keys & values 是可以的。has_section() 也无效,可以和 in (有效)区别使用。

shutil模块[编辑]

import shutil
  • copy():复制文件
  • copy2():复制文件,保留元数据
  • copyfileobj() 将一个文件的内容拷贝的另外一个文件当中
  • copyfile():将一个文件的内容拷贝的另外一个文件当中
  • copytree():复制整个文件目录
  • copymode():拷贝权限
  • copystat():拷贝元数据(状态)
  • rmtree():移除整个目录,无论是否空
  • move():移动文件或者文件夹
  • which():检测命令对应的文件路径 注意:window和linux不太一样。 window的命令都是.exe结尾,linux则不是
  • disk_usage():检测磁盘使用信息
  • make_archive():归档函数,归档操作
  • unpack_archive():解包操作
  • get_archive_formats():获取当前系统已注册的归档文件格式(后缀)
  • get_unpack_formats():获取当前系统已经注册的解包文件格式(后缀)

glob模块[编辑]

glob模块是最简单的模块之一,用通配符查找文件、路径名。三个匹配符是“*”、“?”、“[”,其中“[]”匹配指定范围内的字符。

  • glob.glob 返回所有匹配的文件、路径列表。如果参数recursive=True, 模式“**”匹配任何文件或任何数目的子目录组成的路径;如果pattern以os.sep或os.altsep结尾,则不会匹配文件。“.”开始的文件、子目录是隐藏的,默认不会被匹配,除非明确在模式中指明以“.”开始。
  • glob.iglob 返回匹配的文件、路径的迭代器。
  • glob.escape(pathname):返回的字符串,把“*”、“?”、“[”字符用“[]”包围起来。