logging
简单应用
将日志打印到屏幕
1 import logging
2 logging.debug('debug message')
3 logging.info('info message')
4 logging.warning('warning message')
5 logging.error('error message')
6 logging.critical('critical message')
可见,默认情况下Python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET),默认的日志格式为日志级别:Logger名称:用户输出消息。
灵活配置日志级别,日志格式,输出位置
1 import logging
2 logging.basicConfig(level=logging.DEBUG,
3 format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
4 datefmt='%a,%d %b %Y %H:%M:%S',
5 filename='test.log',
6 ) # filemode='a'
7
8
9 logging.debug('debug message11')
10 logging.info('info message22')
11 logging.warning('hello error33')
12 logging.error('error message44')
13 logging.critical('critical message55')
保存的内容为
Wed,14 Sep 2016 16:09:48 modue_test.py[line:46] DEBUG debug message11
Wed,14 Sep 2016 16:09:48 modue_test.py[line:47] INFO info message22
Wed,14 Sep 2016 16:09:48 modue_test.py[line:48] WARNING hello error33
Wed,14 Sep 2016 16:09:48 modue_test.py[line:49] ERROR error message44
Wed,14 Sep 2016 16:09:48 modue_test.py[line:50] CRITICAL critical message55
可见在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有
filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
format:指定handler使用的日志显示格式。
datefmt:指定日期时间格式。
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用户输出的消息
logger 对象
logging.basicConfig()(用默认日志格式(Formatter)为日志系统建立一个默认的流处理器(StreamHandler),设置基础配置(如日志级别等)并加到root logger(根Logger)中)这几个logging模块级别的函数,另外还有一个模块级别的函数是logging.getLogger([name])(返回一个logger对象,如果没有指定名字将返回root logger)
1 import logging
2
3 logger = logging.getLogger()
4 # 创建一个handler,用于写入日志文件
5 fh = logging.FileHandler('test.log')
6
7 # 再创建一个handler,用于输出到控制台
8 ch = logging.StreamHandler()
9
10 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
11
12 fh.setFormatter(formatter)
13
14 ch.setFormatter(formatter)
15
16 logger.addHandler(fh)
17 logger.addHandler(ch)
18
19 logger.setLevel(logging.DEBUG)
20
21 logger.debug('logger debug message')
22 logger.info('logger info message')
23 logger.warning('logger warning message')
24 logger.error('logger error message')
25 logger.critical('logger critical message')
运行后在文件与屏幕上同时输出
2016-09-14 16:13:43,774 - root - DEBUG - logger debug message
2016-09-14 16:13:43,775 - root - INFO - logger info message
2016-09-14 16:13:43,775 - root - WARNING - logger warning message
2016-09-14 16:13:43,775 - root - ERROR - logger error message
2016-09-14 16:13:43,775 - root - CRITICAL - logger critical message
configparser 模块
来看一个好软件的常见文档格式如下:
1 [DEFAULT]
2 ServerAliveInterval = 45
3 Compression = yes
4 CompressionLevel = 9
5 ForwardX11 = yes
6
7 [bitbucket.org]
8 User = hg
9
10 [topsecret.server.com]
11 Port = 50022
12 ForwardX11 = no
如果想用python生成一个这样的文档怎么做呢?
1 import configparser
2
3 config = configparser.ConfigParser()
4 config["DEFAULT"] = {'ServerAliveInterval': '45',
5 'Compression': 'yes',
6 'CompressionLevel': '9'}
7
8 config['bitbucket.org'] = {}
9 config['bitbucket.org']['User'] = 'hg'
10 config['topsecret.server.com'] = {}
11 topsecret = config['topsecret.server.com']
12 topsecret['Host Port'] = '50022' # mutates the parser
13 topsecret['ForwardX11'] = 'no' # same here
14 config['DEFAULT']['ForwardX11'] = 'yes'<br>
15 with open('example.ini', 'w') as configfile:
16 config.write(configfile)
增删改查
1 import configparser
2
3 config = configparser.ConfigParser()
4
5 #---------------------------------------------查
6 print(config.sections()) #[]
7
8 config.read('example.ini')
9
10 print(config.sections()) #['bitbucket.org', 'topsecret.server.com']
11
12 print('bytebong.com' in config)# False
13
14 print(config['bitbucket.org']['User']) # hg
15
16 print(config['DEFAULT']['Compression']) #yes
17
18 print(config['topsecret.server.com']['ForwardX11']) #no
19
20
21 for key in config['bitbucket.org']:
22 print(key)
23
24
25 # user
26 # serveraliveinterval
27 # compression
28 # compressionlevel
29 # forwardx11
30
31
32 print(config.options('bitbucket.org'))#['user', 'serveraliveinterval', 'compression', 'compressionlevel', 'forwardx11']
33 print(config.items('bitbucket.org')) #[('serveraliveinterval', '45'), ('compression', 'yes'), ('compressionlevel', '9'), ('forwardx11', 'yes'), ('user', 'hg')]
34
35 print(config.get('bitbucket.org','compression'))#yes
36
37
38 #---------------------------------------------删,改,增(config.write(open('i.cfg', "w")))
39
40
41 config.add_section('yuan')
42
43 config.remove_section('topsecret.server.com')
44 config.remove_option('bitbucket.org','user')
45
46 config.set('bitbucket.org','k1','11111')
47
48 config.write(open('i.cfg', "w"))
49
50 增删改查
View Code
json & pickle
序列化
我们把对象(变量)从内存中变成可存储或传输的过程称为序列化
序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上
反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化
json
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为json,因为json表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。json不仅是标准格式,而且比XML更快,而且可以直接在Wab页面中读取,非常方便。
1 import json
2
3 dic={'name':'alvin','age':23,'sex':'male'}
4 print(type(dic)) #<class 'dict'>
5
6 j=json.dumps(dic)
7 print(type(j)) #<class 'str'>
8
9
10 f=open('序列化对象','w')
11 f.write(j) #-------------------等价于json.dump(dic,f)
12 f.close()
13 #-----------------------------反序列化<br>
14 import json
15 f=open('序列化对象')
16 data=json.loads(f.read()) # 等价于data=json.load(f)
1 import json
2 #dct="{'1':111}"#json 不认单引号
3 #dct=str({"1":111})#报错,因为生成的数据还是单引号:{'one': 1}
4
5 dct='{"1":"111"}'
6 print(json.loads(dct))
7
8 #conclusion:
9 # 无论数据是怎样创建的,只要满足json格式,就可以json.loads出来,不一定非要dumps的数据才能loads
10
11 注意点
保存的时候有两个方法dump和dumps
读取的时候有两个方法load和loads
1 import json
2 # import pickle
3 f = open("666.txt", "w")
4
5 dic = {"j": "d", "6": "dd"}
6 # dic = json.dumps(dic)
7 # f.write(dic)
8 json.dump(dic, f)
9 # dic = pickle.dumps(dic)
10 print(type(dic))
11
12
13 f.close()
14
15 ######### 注意两种方法的不同 ##########
16 import json
17
18 f = open("666.txt", "r")
19
20 # data = json.loads(f.read())
21 data = json.load(f)
22 print(data)
23 # print(type(f.read()))
24 f.close()
pickle
pickle的使用方法与json类似,但是pickle只能用于python,并且能保存json不能保存的类型
subprocess
subprocess模块的主要功能是执行外部的命令和程序
subprocess模块允许一个进程创建一个新的子进程,通过管道连接到子进程的stdin/stdout/stderr,获取子进程的返回值等操作
模块有一个重要类: Popen
1 # Popen它的构造函数如下:
2
3 subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None,stderr=None, preexec_fn=None, close_fds=False, shell=False,<br> cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)
1 # 参数args可以是字符串或者序列类型(如:list,元组),用于指定进程的可执行文件及其参数。
2 # 如果是序列类型,第一个元素通常是可执行文件的路径。我们也可以显式的使用executeable参
3 # 数来指定可执行文件的路径。在windows操作系统上,Popen通过调用CreateProcess()来创
4 # 建子进程,CreateProcess接收一个字符串参数,如果args是序列类型,系统将会通过
5 # list2cmdline()函数将序列类型转换为字符串。
6 #
7 #
8 # 参数bufsize:指定缓冲。我到现在还不清楚这个参数的具体含义,望各个大牛指点。
9 #
10 # 参数executable用于指定可执行程序。一般情况下我们通过args参数来设置所要运行的程序。如
11 # 果将参数shell设为True,executable将指定程序使用的shell。在windows平台下,默认的
12 # shell由COMSPEC环境变量来指定。
13 #
14 # 参数stdin, stdout, stderr分别表示程序的标准输入、输出、错误句柄。他们可以是PIPE,
15 # 文件描述符或文件对象,也可以设置为None,表示从父进程继承。
16 #
17 # 参数preexec_fn只在Unix平台下有效,用于指定一个可执行对象(callable object),它将
18 # 在子进程运行之前被调用。
19 #
20 # 参数Close_sfs:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会
21 # 继承父进程的输入、输出、错误管道。我们不能将close_fds设置为True同时重定向子进程的标准
22 # 输入、输出与错误(stdin, stdout, stderr)。
23 #
24 # 如果参数shell设为true,程序将通过shell来执行。
25 #
26 # 参数cwd用于设置子进程的当前目录。
27 #
28 # 参数env是字典类型,用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父
29 # 进程中继承。
30 #
31 # 参数Universal_newlines:不同操作系统下,文本的换行符是不一样的。如:windows下
32 # 用’/r/n’表示换,而Linux下用’/n’。如果将此参数设置为True,Python统一把这些换行符当
33 # 作’/n’来处理。
34 #
35 # 参数startupinfo与createionflags只在windows下用效,它们将被传递给底层的
36 # CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等。
37
38 parameter
参数介绍
简单命令
1 # 此为linux下运行
2 import subprocess
3
4 a=subprocess.Popen('ls')# 创建一个新的进程,与主进程不同步
5
6 print('>>>>>>>',a)#a是Popen的一个实例对象
7
8 '''
9 >>>>>>> <subprocess.Popen object at 0x10185f860>
10 __init__.py
11 __pycache__
12 log.py
13 main.py
14
15 '''
16
17 # subprocess.Popen('ls -l',shell=True)
18
19 # subprocess.Popen(['ls','-l'])
subprocess.PIPE
在创建Popen对象时,subprocess.PIPE可以初始化stdin,std,out,stderr参数。表示与子进程通信的标准流
1 import subprocess
2
3 # subprocess.Popen('ls')
4 p=subprocess.Popen('ls',stdout=subprocess.PIPE)#结果跑哪去啦?
5
6 print(p.stdout.read())#这这呢:b'__pycache__\nhello.py\nok.py\nweb\n'
这是因为subprocess创建了子进程,结果本来在子进程中,if想要执行结果转到主进程中,就需要一个管道,即: stdout = subprocess.PIPE
Popen的方法
Popen.poll()
用于检查子进程是否已经结束。设置并返回returncode属性。
Popen.wait()
等待子进程结束。设置并返回returncode属性。
Popen.communicate(input=None)
与子进程进行交互。向stdin发送数据,或从stdout和stderr中读取数据。可选参数input指定发送到子进程的参数。 Communicate()返回一个元组:(stdoutdata, stderrdata)。注意:如果希望通过进程的stdin向其发送数据,在创建Popen对象的时候,参数stdin必须被设置为PIPE。同样,如 果希望从stdout和stderr获取数据,必须将stdout和stderr设置为PIPE。
Popen.send_signal(signal)
向子进程发送信号。
Popen.terminate()
停止(stop)子进程。在windows平台下,该方法将调用Windows API TerminateProcess()来结束子进程。
Popen.kill()
杀死子进程。
Popen.stdin
如果在创建Popen对象是,参数stdin被设置为PIPE,Popen.stdin将返回一个文件对象用于策子进程发送指令。否则返回None。
Popen.stdout
如果在创建Popen对象是,参数stdout被设置为PIPE,Popen.stdout将返回一个文件对象用于策子进程发送指令。否则返回 None。
Popen.stderr
如果在创建Popen对象是,参数stdout被设置为PIPE,Popen.stdout将返回一个文件对象用于策子进程发送指令。否则返回 None。
Popen.pid
获取子进程的进程ID。
Popen.returncode
获取进程的返回值。如果进程还没有结束,返回None。
subprocess模块的工具函数
supprocess模块提供了一些函数,方便我们用于创建进程来实现一些简单的功能。
subprocess.call(*popenargs, **kwargs)
运行命令。该函数将一直等待到子进程运行结束,并返回进程的returncode。如果子进程不需要进行交 互,就可以使用该函数来创建。
subprocess.check_call(*popenargs, **kwargs)
与subprocess.call(*popenargs, **kwargs)功能一样,只是如果子进程返回的returncode不为0的话,将触发CalledProcessError异常。在异常对象中,包 括进程的returncode信息。
check_output(*popenargs, **kwargs) # 重要
与call()方法类似,以byte string的方式返回子进程的输出,如果子进程的返回值不是0,它抛出CalledProcessError异常,这个异常中的returncode包含返回码,output属性包含已有的输出。
getstatusoutput(cmd)/getoutput(cmd)
这两个函数仅仅在Unix下可用,它们在shell中执行指定的命令cmd,前者返回(status, output),后者返回output。其中,这里的output包括子进程的stdout和stderr。
1 import subprocess
2
3 #1
4 # subprocess.call('ls',shell=True)
5 '''
6 hello.py
7 ok.py
8 web
9 '''
10 # data=subprocess.call('ls',shell=True)
11 # print(data)
12 '''
13 hello.py
14 ok.py
15 web
16 '''
17
18 #2
19 # subprocess.check_call('ls',shell=True)
20
21 '''
22 hello.py
23 ok.py
24 web
25 '''
26 # data=subprocess.check_call('ls',shell=True)
27 # print(data)
28 '''
29 hello.py
30 ok.py
31 web
32 '''
33 # 两个函数区别:只是如果子进程返回的returncode不为0的话,将触发CalledProcessError异常
34
35
36
37 #3
38 # subprocess.check_output('ls')#无结果
39
40 # data=subprocess.check_output('ls')
41 # print(data) #b'hello.py\nok.py\nweb\n'
42
43 演示