银角大王之博客二:
http://www.cnblogs.com/wupeiqi/articles/4911365.html
1、编码转换介绍
<1> . python2里有二种字符串unicode和str,其中unicode是最底层、最纯的,会根据终端的编码进行转化展示
- str可以看作是unicode字符串经过某种编码后的字节组成的数组
- unicode是真正意义上的字符串
- 通过 encode 可以将unicode类型编码为str类型
- 通过 decode 可以将str类型解码为unicode类型
- python 会隐式地进行编码、解码,默认采用 ascii
- 所有的编码、解码错误都是由于所选的编码、解码方式无法表示某些字符造成的
Python 2 悄悄掩盖掉了 byte 到 unicode 的转换,只要数据全部是 ASCII 的话,所有的转换都是正确的,一旦一个非 ASCII 字符偷偷进入你的程序,那么默认的解码将会失效,从而造成 UnicodeDecodeError 的错误。py2编码让程序在处理 ASCII 的时候更加简单。你复出的代价就是在处理非 ASCII 的时候将会失败。
一般硬盘存储或传输为utf-8(因为省空间、省带宽),读入内存中为unicode,二者如何转换
a = '你好' '\xe4\xbd\xa0\xe5\xa5\xbd' <type 'str'>
b = u'你好' u'\u4f60\u597d' <type 'unicode'>
a.decode('utf-8') u'\u4f60\u597d' (utf-8格式解码为unicode)
b.encode('utf-8') '\xe4\xbd\xa0\xe5\xa5\xbd' (unicode格式加密为utf-8)
注:在python2.7版本中需要如上转换,在脚本中如要显示中文,
只要在文件开头加入 # _*_ coding: UTF-8 _*_ 或者 #coding=utf-8 就行了
<2> . python3也有两种数据类型:str和bytes; str类型存unicode数据,bytse类型存bytes数据,与py2比只是换了一下名字而已。
要将str类型转化为bytes类型,使用encode()内置函数;反过来,使用decode()函数
<3> . python2与python3字符串编码的区别
python3默认使用的是str类型对字符串编码,默认使用bytes操作二进制数据流,两者不能混淆!!
Python3有两种表示字符序列的类型:bytes和str。前者的实例包含原始的8位值,后者的实例包含Unicode字符。Python2也有两种表示字符序列的类型,分别叫做str和Unicode,与Python3不同的是,str实例包含原始的8位值;而unicode的实例,则包含Unicode字符。
2、字符串的常用函数format:
S.format(*args, **kwargs) -> string
Return a formatted version of S, using substitutions from args and kwargs.
The substitutions are identified by braces ('{' and '}').
name1 = "I am {0},age is {1}" name1.format('kevin',33) li = ['kevin',33] name1.format(*li) name2 = "I am {ss},age is {dd}" name2.format(ss='kevin',dd=33) dic = {'ss': 'kevin','dd':33} name2.format(**dic)
3、元组的元素是不能被修改,但元素的元素能可以被被修改的
>>> aa = (1,2,'a','b',['a',1,'b',2]) >>> aa (1, 2, 'a', 'b', ['a', 1, 'b', 2]) >>> aa[-1] ['a', 1, 'b', 2] >>> aa[-1].append('aaaa') >>> aa (1, 2, 'a', 'b', ['a', 1, 'b', 2, 'aaaa'])
4、字典的循环
当数据量达到上百万时,循环字典就不适合用dict.items(),因为首先会把一对对key和value转化为列表,然后在循环遍历输出,会增加内存使用。建议使用如下:
>>> a = {1:'a',2:'b'} >>> for k in aa:print(k,aa[k]) (1, 'a') (2, 'b')
>>> for k in aa.keys():print(k,aa[k]) (1, 'a') (2, 'b')
5、调用系统命令,并存入变量:
1).import os
a = os.system('df -Th') 可以获取命令执行后的返回值,但是获取不了命令的输出内容
b = os.popen('df -Th','r') 可以获取命令的输出内容,但是获取不了命令执行后的返回值
a = os.popen("ls -l",'r')
for i in a.readlines():
print(i.strip())
c = os.path.dirname(os.path.abspath(__file__)) 获取当前的目录
2).import commands
c = commands.getoutput('df -Th') 返回一个字符串
commands.getstatusoutput(cmd)返回(status,output)
commands.getoutput(cmd)只返回输出结果
3). import subprocess
<1>. call
执行命令,返回状态码,shell = True允许shell命令时字符串形式
subprocess.call([
"ls"
,
"-l"
])
subprocess.call(
"exit 1"
, shell
=
True
)
<2>. check_call
执行命令,如果执行状态码是0,则返回0,否则抛出异常
subprocess.check_call([
"ls"
,
"-l"
])
subprocess.check_call(
"exit 1"
, shell
=
True
)
<3>.check_output
执行命令,如果状态码是0,则返回执行结果,否则抛出异常
subprocess.check_output([
"echo"
,
"Hello World!"
])
subprocess.check_output(
"exit 1"
, shell
=
True
)
用于执行复杂的系统命令
参数:
- args: 可以是字符串或者序列类型(如:list, tuple)。默认的,要执行的程序应该是序列的第一个字段,如果是单个字符串,它的解析依赖于平台。在unix中,如果args是一个字符串,那么这个字符串解释成被执行程序的名字或路径,然而,这种情况只能用在不需要参数的程序。
- bufsieze: 指定缓冲。0表示无缓冲,1表示缓冲,任何其他的整数值表示缓冲大小,负数值表示使用系统默认缓冲,通常表示完全缓冲。默认值为0即没有缓冲。
- stdin, stdout, stderr:分别表示程序的标准输入,输出,错误句柄
- preexec_fn : 只在unix平台有效,用于指定一个可执行对象,它将在子进程中运行之前被调用
- close_fds : 在windows平台下,如果close_fds被设置为true,则新创建的子进程将不会继承父进程的输入,输出,错误管道。所以不能将close_fds设置为true同时重定向子进程的标准输入,输出与错误。
- shell : 默认值为False, 声明了是否使用shell来执行程序,如果shell=True,它将args看做一个字符串,而不是一个序列。在unix系统中,且shell=True, shell默认使用/bin/sh。
- cwd : 用于设置子进程的当前目录。当它不为None时,子程序在执行前,它的当前路径会被替换成cwd的值。这个路径并不会被添加到可执行程序的搜索路径,所以cwd不能是相对路径。
- env : 用于指定子进程的环境变量。如果env=None,子进程的环境变量将从父进程中继承。当它不为None时,它是新进程的环境变量的映射。可以用它来代替当前进程的环境。
- universal_newlines : 不同系统的换行符不同, 文件对象stdout和stderr都被以文本文件的方式打开
- startupinfo 与 createionflags只在windows下生效。将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等
例:
subprocess.Popen(["df","-Th"])
注:Popen对象创建后,主程序不会自动等待子进程完成,我们必须调用对象的wait()方法,父进程才会等待 (也就是阻塞block)
child = subprocess.Popen(["ping","-c","5","www.baidu.com"])
child.wait()
print("parent process")
此外,你还可以在父进程中对子进程进行其它操作,比如我们上面例子中的child对象:
child.poll() # 检查子进程状态
child.kill() # 终止子进程
child.send_signal() # 向子进程发送信号
child.terminate() # 终止子进程
子进程的PID存储在child.pid
实例:
#!/usr/bin/python3 import subprocess,os,sys #obj = subprocess.Popen("mkdir t3", shell=True, cwd='/tmp',) # #obj = subprocess.Popen(["python3"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) #obj.stdin.write("a = 35 * 20 + 31 \n") #obj.stdin.write("print(a)\n") #obj.stdin.write("b = 3 / 0\n") #obj.stdin.write("print(b)") #obj.stdin.close() # #cmd_out = obj.stdout.read() #obj.stdout.close() #cmd_error = obj.stderr.read() #obj.stderr.close() # #print(cmd_out) #print("the cmd_error is %s" % cmd_error) # #obj1 = subprocess.Popen(["python3"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) # #obj1.stdin.write("a = 35 * 20 + 31 \n") #obj1.stdin.write("print(a)") #out_error_list = obj1.communicate() #print(out_error_list) # # # #obj2 = subprocess.Popen(["python3"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) # #out_error_list = obj2.communicate('print("hello")') #print(out_error_list) # # #child1 = subprocess.Popen("ls bb",shell=True, stdout=subprocess.PIPE) #print(child1.stdout.read()) #child2 = subprocess.Popen(["cat"], stdin=child1.stdout,stdout=subprocess.PIPE) #print(child2.stdout.read()) #out = child2.communicate() #print(out[0].decode('utf-8')) # # child = subprocess.Popen(["cat"], stdin=subprocess.PIPE,stdout=subprocess.PIPE) child.communicate('bb'.encode('utf-8')) cc = child.stdout.read() print(cc) child.stdout.close() #output_file = open("abc",'w'); #return_code = subprocess.call(['ls','-l'],stdout=output_file); #output_file.close(); #print(return_code);
6、sys调用
import sys
sys.exit
print sys.argv
sys.path
7、导入模板方法:
1.import sys [as newname]
多次重复使用import语句时,不会重新加载被指定的模块,只是把对该模块的内存地址给引用到本地变量环境。
2.from sys import argv或(*)
3.reload()
reload会重新加载已加载的模块,但原来已经使用的实例还是会使用旧的模块,而新生产的实例会使用新的模块;reload后还是用原来的内存地址;不能支持from。。import。。格式的模块进行重新加载。
建议使用第一种,第二种导入的对象或变量会与当前的变量会冲突。
8、字典复制:
dict = {'name':'wang', 'sex':'m', 'age':34, 'job':'it'}
info = dict ##别名 (二个字典指向内存的同一地址空间)
info1 = dict.copy() #shadow copy 浅复制(嵌套字典第一层独立,第二层以下相关联)
import copy
copy.copy() #shadow copy 浅复制
copy.deepcopy() #deep copy 深复制(完全独立)
注:浅复制下的关联只是针对字典初始状态包含的嵌套对象,后新加的不会
例:
>>> dict
{'info': ['a', 'b', 1, 2], 'job': 'it', 'sex': 'm', 'age': 40, 'name': 'wang'}
>>> dict_alias = dict
>>> dict_copy = copy.copy(dict)
>>> dict_deep = copy.deepcopy(dict)
#添加、改变、删除第一层的对象键值,浅复制和深复制都不受影响
>>> dict['age'] = 32
>>> del dict['sex']
>>> dict
{'info': ['a', 'b', 1, 2], 'job': 'it', 'age': 32, 'name': 'wang'}
>>> dict_alias
{'info': ['a', 'b', 1, 2], 'job': 'it', 'age': 32, 'name': 'wang'}
>>> dict_copy
{'info': ['a', 'b', 1, 2], 'job': 'it', 'age': 40, 'name': 'wang', 'sex': 'm'}
>>> dict_deep
{'info': ['a', 'b', 1, 2], 'job': 'it', 'age': 40, 'name': 'wang', 'sex': 'm'}
#改变、删除原有的第二层的对象键值,浅复制受影响,而深复制都不受影响
>>> dict['info'][2] = 100
>>> dict
{'info': ['a', 'b', 100, 2], 'job': 'it', 'age': 32, 'name': 'wang'}
>>> dict_alias
{'info': ['a', 'b', 100, 2], 'job': 'it', 'age': 32, 'name': 'wang'}
>>> dict_copy
{'info': ['a', 'b', 100, 2], 'job': 'it', 'age': 40, 'name': 'wang', 'sex': 'm'}
>>> dict_deep
{'info': ['a', 'b', 1, 2], 'job': 'it', 'age': 40, 'name': 'wang', 'sex': 'm'}
#添加第二层的对象,浅复制和深复制都不受影响
>>> dict['new'] = {'a':1, 'b':2, 'c':5}
>>> dict
{'info': ['a', 'b', 100, 2], 'name': 'wang', 'age': 32, 'job': 'it', 'new': {'a': 1, 'c': 5, 'b': 2}}
>>> dict_alias
{'info': ['a', 'b', 100, 2], 'name': 'wang', 'age': 32, 'job': 'it', 'new': {'a': 1, 'c': 5, 'b': 2}}
>>> dict_copy
{'info': ['a', 'b', 100, 2], 'job': 'it', 'age': 40, 'name': 'wang', 'sex': 'm'}
>>> dict_deep
{'info': ['a', 'b', 1, 2], 'job': 'it', 'age': 40, 'name': 'wang', 'sex': 'm'}
9、内置函数说明:
__name__:主文件时返回main,否则返回文件名,可用来判断是否说主文件还是导入模块;
__file__:文件的绝对路径;
__doc__:文件开头的注释说明
例:
'''
created by 2015-12-18
@author: kevin
'''
if __name__ == '__main__':
print('this is main file')
print(__file__)
print(__doc__)