OS模块
用于系统级别的操作
os.getcdw()
获取当前目录,及python脚本执行时所在的目录
>>> import os
>>> os.getcwd()
'/home/dy'
os.chdir(“dirname”)
改变当前目录,相当于shell的cd
>>> os.chdir("/home/dy/iso")
>>> os.getcwd()
'/home/dy/iso'
os.curdie
返回当前目录:’.’
>>> os.curdir
'.'
os.pardir
返回上一级目录:”..”
>>> os.pardir
'..'
os.makedirs(“dirname1/dirname2”)
创建目录,也可以创建多层目录
>>> os.maked
os.makedev( os.makedirs(
>>> os.makedirs("xiaoming/xiaowang")
>>>
la@la:~/python_test$ ls
xiaoming
la@la:~/python_test$ ls -R xiaoming/
xiaoming/:
xiaowang
xiaoming/xiaowang:
os.removedirs(‘dirname1’)
递归删除目录,若当前目录为空则删除后返回上一级目录,若还为空,再删除,再返回上一级目录
>>> import os
>>> os.removedirs("xiaoming/xiaowang")
>>>
dy@dy:~/python_test$ ls
dy@dy:~/python_test$
os.mkdir(“dirname”)
生成单级目录,相当于shell的mkdir
>>> os.mkdir("xiaozhang")
>>>
dy@dy:~/python_test$ ls
xiaozhang
os.rmdir(“dirname”)
删除单级目录,若目录不为空则无法删除,报错
>>> os.rmdir("xiaozhang")
>>>
dy@dy:~/python_test$ ls
dy@dy:~/python_test$
os.listdir(“dirname”)
列出目录的所有文件和子目录,包括隐藏文件,并以列表的形式打印
>>> os.listdir("/")
['swapfile', 'cdrom', 'vmlinuz', 'lost+found', 'usr', 'bin', 'dev', 'initrd.img', 'mnt', 'home', 'srv', 'tmp', 'initrd.img.old', 'root', 'lib64', 'var', 'lib', 'boot', 'run', 'media', 'sbin', 'snap', 'vmlinuz.old', 'proc', 'etc', 'sys']
>>>
os.remove(“filename”)
删除一个文件
>>> os.listdir(".")
['test.txt']
>>> os.remove("test.txt")
>>> os.listdir(".")
[]
os.rename(“oldname”,”newname”)
重命名文件、目录
dy@dy:~/python_test$ touch test.txt
dy@dy:~/python_test$ python3
Python 3.5.3 (default, Jan 19 2017, 14:11:04)
[GCC 6.3.0 20170118] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.rename("test.txt", "test_new.txt")
>>>
dy@dy:~/python_test$ ls
test_new.txt
os.stat(“path/filename”)
获取目录、文件信息
>>> import os
>>> os.stat("/home")
os.stat_result(st_mode=16877, st_ino=19791873, st_dev=2050, st_nlink=3, st_uid=0, st_gid=0, st_size=4096, st_atime=1493756523, st_mtime=1493756272, st_ctime=1493756272)
>>> os.stat("test_new.txt")
os.stat_result(st_mode=33188, st_ino=19925258, st_dev=2050, st_nlink=1, st_uid=1000, st_gid=1000, st_size=0, st_atime=1493795614, st_mtime=1493795614, st_ctime=1493795641)
>>>
os.sep
输出操作系统下的路径分隔符
>>> os.sep
'/'
os.linesep
返回当前操作系统的行终止符
>>> os.linesep
'\n'
os.pathsrp()
用户分割文件与路径的字符串
SyntaxError: invalid syntax
>>> os.pathsep
':'
os.name
返回当前使用的平台
>>> os.name
'posix'
os.system(“bash cmd”)
运行系统命令,输出结果,返回值为空
>>> os.system("ls")
test_new.txt
0
>>>
os.environ
获取当前系统的环境变量
>>> os.environ
environ({'PWD'。。。略;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:'})
os.path.abspath(path)
返回path规范化的绝对路径
>>> os.path.abspath("./")
'/home/dy/python_test'
>>>
os.path.split(path)
将路径分割成路径文件名组成的元组,其实只是将路径的最后一项分割出来,不管是不是文件
>>> os.path.split("/usr/bin")
('/usr', 'bin')
os.path.dirname(path)
返回path的目录。其实就是os.path.split(path)的第一个元素
>>> os.path.dirname("/usr/bin")
'/usr'
os.path.basename(path)
返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
>>> os.path.basename("/usr/bin")
'bin'
os.path.exists(path)
如果路径存在,返回True,不存在返回Flase
>>> os.path.exists("/home")
True
>>> os.path.exists("/homex")
False
os.path.isabs(path)
如果时绝对路径返回True,不是返回False
>>> os.path.isabs("home")
False
>>> os.path.isabs("/home")
True
os.path.isfile(path)
如果path是一个存在的文件,返回True,否则返回False
>>> os.path.isfile("test_new.txt")
True
>>> os.path.isfile("aaa")
False
os.path.isdir(path)
如果path是一个存在的目录,返回True,否则返回False
>>> os.path.isdir("home")
False
>>> os.path.isdir("/home")
True
os.path.join(path1[, path2[, …]])
将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
>>> os.path.join("/home","/bin")
'/bin'
>>> os.path.join("/home","/bin")
'/bin'
>>> os.path.join("/home","bin")
'/home/bin'
>>> os.path.join("/home","bin",'dy')
'/home/bin/dy'
>>> os.path.join("home","/bin",'dy')
'/bin/dy'
os.path.getatime(path)
返回path所指向的文件或者目录的最后存取时间
>>> os.path.getatime("test_new.txt")
1493795614.4796455
os.path.getmtime(path)
返回path所指向的文件或者目录的最后修改时间
>>> os.path.getmtime("test_new.txt")
1493795614.4796455
os.popen(“cmd”)
执行命令并将结果返回,结果将保存
>>> os.popen("ls")
<os._wrap_close object at 0x7fd9ee2c1278>
>>> os.popen("ls").read()
'test_new.txt\n'
sys模块
sys.argv
返回命令行参数的列表,第一个元素的自己
>>> import sys
>>> sys.argv
['']
sys.exit(n)
退出,n为退出级别,n=0为正常退出
>>> import sys
>>> sys.exit(3)
dy@dy:~$
sys.version
获取Python解释程序的版本信息
>>> sys.version
'3.5.3 (default, Jan 19 2017, 14:11:04) \n[GCC 6.3.0 20170118]'
sys.maxint(仅限2.X)
最大的Int值
>>> sys.maxint
9223372036854775807
sys.path
返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
>>> sys.path
['', '/usr/lib/python35.zip', '/usr/lib/python3.5', '/usr/lib/python3.5/plat-x86_64-linux-gnu', '/usr/lib/python3.5/lib-dynload', '/usr/local/lib/python3.5/dist-packages', '/usr/lib/python3/dist-packages']
sys.platform
返回操作系统平台名称
>>> sys.platform
'linux'
sys.stdin\sys.stdout\sys.stderror
输入相关、输出相关、错误相关
shutil模块
高级的文件、文件夹处理以及压缩模块
shutil.copyfileobj()
将一个文件中的内容复制到另一个文件
dy@dy:~/python_test/Day06$ cat old_file
This is old file
dy@dy:~/python_test/Day06$ cat new_file
This is new file
dy@dy:~/python_test/Day06$ vim shutil_test.py
dy@dy:~/python_test/Day06$ python3 shutil_test.py
dy@dy:~/python_test/Day06$ cat new_file
This is old file
dy@dy:~/python_test/Day06$ cat shutil_test.py
#!/usr/bin/env python3
import shutil
shutil.copyfileobj(open("old_file", "r"), open("new_file", "w"))
shutil.copyfile()
将一个文件的内容复制到另一文件中
dy@dy:~/python_test/Day06$ cat old_file
This is old file
dy@dy:~/python_test/Day06$ cat new_file
This is new file
dy@dy:~/python_test/Day06$ vim shutil_copyfile.py
dy@dy:~/python_test/Day06$ python3 shutil_copyfile.py
dy@dy:~/python_test/Day06$ cat new_file
This is old file
dy@dy:~/python_test/Day06$ cat shutil_copyfile.py
#!/usr/bin/env python3
import shutil
shutil.copyfile("old_file", "new_file")
shutil.copymode()
仅拷贝权限,内容,组,用户不变
dy@dy:~/python_test/Day06$ ll old_file
-r--r--r-- 1 dy dy 17 5月 4 21:04 old_file
dy@dy:~/python_test/Day06$ ll new_file
-rw-rw-rw- 1 dy dy 17 5月 4 21:17 new_file
dy@dy:~/python_test/Day06$ python3 shutil_copymode.py
dy@dy:~/python_test/Day06$ ll new_file
-r--r--r-- 1 dy dy 17 5月 4 21:17 new_file
dy@dy:~/python_test/Day06$ cat shutil_copymode.py
#!/usr/bin/env python3
import shutil
shutil.copymode("old_file", "new_file")
shutil.copystat()
仅拷贝状态的信息,包括:mode bits, atime, mtime, flags
dy@dy:~/python_test/Day06$ stat old_file
文件:old_file
大小:17 块:8 IO 块:4096 普通文件
设备:802h/2050d Inode:19925260 硬链接:1
权限:(0444/-r--r--r--) Uid:( 1000/ dy) Gid:( 1000/ dy)
最近访问:2017-05-04 21:26:25.184428561 +0800
最近更改:2017-05-04 21:04:20.071845988 +0800
最近改动:2017-05-04 21:19:03.547170350 +0800
创建时间:-
dy@dy:~/python_test/Day06$ stat new_file
文件:new_file
大小:17 块:8 IO 块:4096 普通文件
设备:802h/2050d Inode:19925268 硬链接:1
权限:(0444/-r--r--r--) Uid:( 1000/ dy) Gid:( 1000/ dy)
最近访问:2017-05-04 21:26:29.312565130 +0800
最近更改:2017-05-04 21:17:19.480120152 +0800
最近改动:2017-05-04 21:19:26.733391980 +0800
创建时间:-
dy@dy:~/python_test/Day06$ python3 shutil_copystat.py
dy@dy:~/python_test/Day06$ stat new_file
文件:new_file
大小:17 块:8 IO 块:4096 普通文件
设备:802h/2050d Inode:19925268 硬链接:1
权限:(0444/-r--r--r--) Uid:( 1000/ dy) Gid:( 1000/ dy)
最近访问:2017-05-04 21:26:25.184428561 +0800
最近更改:2017-05-04 21:04:20.071845988 +0800
最近改动:2017-05-04 21:27:03.725668546 +0800
创建时间:-
dy@dy:~/python_test/Day06$ cat shutil_copystat.py
#!./uer/bin/env python3
import shutil
shutil.copystat("old_file", "new_file")
shutil.copy()
拷贝文件和权限
dy@dy:~/python_test/Day06$ ll old_file
-rw-rw-rw- 1 dy dy 17 5月 4 21:04 old_file
dy@dy:~/python_test/Day06$ ll new_file
-rwxrwxrwx 1 dy dy 17 5月 4 21:04 new_file*
dy@dy:~/python_test/Day06$ python3 shutil_copy.py
dy@dy:~/python_test/Day06$ cat new_file
This is old file
dy@dy:~/python_test/Day06$ ll new_file
-rw-rw-rw- 1 dy dy 17 5月 4 21:34 new_file
dy@dy:~/python_test/Day06$ cat shutil_copy.py
#!/usr/bin/env python3
import shutil
shutil.copy("old_file", "new_file")
shutil.copy2()
拷贝文件和状态信息和权限
dy@dy:~/python_test/Day06$ stat old_file
文件:old_file
大小:17 块:8 IO 块:4096 普通文件
设备:802h/2050d Inode:19925260 硬链接:1
权限:(0666/-rw-rw-rw-) Uid:( 1000/ dy) Gid:( 1000/ dy)
最近访问:2017-05-04 21:34:31.976742627 +0800
最近更改:2017-05-04 21:04:20.071845988 +0800
最近改动:2017-05-04 21:32:11.721692564 +0800
创建时间:-
dy@dy:~/python_test/Day06$ stat new_file
文件:new_file
大小:17 块:8 IO 块:4096 普通文件
设备:802h/2050d Inode:19925268 硬链接:1
权限:(0777/-rwxrwxrwx) Uid:( 1000/ dy) Gid:( 1000/ dy)
最近访问:2017-05-04 21:34:40.104913373 +0800
最近更改:2017-05-04 21:34:31.976742627 +0800
最近改动:2017-05-04 21:55:43.526215342 +0800
创建时间:-
dy@dy:~/python_test/Day06$ ll old_file
-rw-rw-rw- 1 dy dy 17 5月 4 21:04 old_file
dy@dy:~/python_test/Day06$ ll new_file
-rwxrwxrwx 1 dy dy 17 5月 4 21:34 new_file*
dy@dy:~/python_test/Day06$ python3 shutil_copy2.py
dy@dy:~/python_test/Day06$ ll new_file
-rw-rw-rw- 1 dy dy 17 5月 4 21:04 new_file
dy@dy:~/python_test/Day06$ stat new_file
文件:new_file
大小:17 块:8 IO 块:4096 普通文件
设备:802h/2050d Inode:19925268 硬链接:1
权限:(0666/-rw-rw-rw-) Uid:( 1000/ dy) Gid:( 1000/ dy)
最近访问:2017-05-04 21:34:31.976742627 +0800
最近更改:2017-05-04 21:04:20.071845988 +0800
最近改动:2017-05-04 21:56:59.722551425 +0800
创建时间:-
dy@dy:~/python_test/Day06$ cat shutil_copy2.py
#!/usr/bin/env python3
import shutil
shutil.copy2("old_file", "new_file")
shutil.copytree(src, dst, symlinks=False, ignore=None)
递归拷贝文件夹
shutil.ignore_patterns(*patterns) 写再ignore处,表示不拷贝特定的文件
dy@dy:~/python_test$ python3 shutil_copytree.py
dy@dy:~/python_test$ ls test
new_file old_file
dy@dy:~/python_test$ ls Day06/
new_file shutil_copyfile.py shutil_copystat.py
old_file shutil_copymode.py shutil_test.py
shutil_copy2.py shutil_copy.py
dy@dy:~/python_test$ cat shutil_copytree.py
#!/usr/bin/env python3
import shutil
shutil.copytree("Day06", "test", symlinks=False, ignore=shutil.ignore_patterns("*py","^s"))
#目标目录时新的。不能是以存在的
shutil.rmtree(path[, ignore_errors[, onerror]])
递归的去删除文件
dy@dy:~/python_test/Day06$ ls test/
new_file old_file
dy@dy:~/python_test/Day06$ python3 shutil_rmtree.py
dy@dy:~/python_test/Day06$ ls test/
ls: 无法访问'test/': 没有那个文件或目录
shutil.move(src, dst)
递归的去移动文件,它类似mv命令,其实就是重命名。
dy@dy:~/python_test/Day06$ ls
new_file shutil_copymode.py shutil_rmtree.py
old_file shutil_copy.py shutil_test.py
shutil_copy2.py shutil_copystat.py test
shutil_copyfile.py shutil_move.py
dy@dy:~/python_test/Day06$
dy@dy:~/python_test/Day06$
dy@dy:~/python_test/Day06$ python3 shutil_move.py
dy@dy:~/python_test/Day06$ ls
new_file shutil_copymode.py shutil_rmtree.py
old_file shutil_copy.py shutil_test.py
shutil_copy2.py shutil_copystat.py test_new
shutil_copyfile.py shutil_move.py
dy@dy:~/python_test/Day06$ cat shutil_move.py
#!/usr/bin/env python3
import shutil
shutil.move("test", "test_new")
shutil.make_archive(base_name, format,…)
创建压缩包并返回文件路径,例如:zip、tar
参数:
base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
如:www =>保存至当前路径
如:/Users/wupeiqi/www =>保存至/Users/wupeiqi/
format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
root_dir: 要压缩的文件夹路径(默认当前目录)
owner: 用户,默认当前用户
group: 组,默认当前组
logger: 用于记录日志,通常是logging.Logger对象
dy@dy:~/python_test/Day06$ ls
new_file shutil_copymode.py shutil_move.py
old_file shutil_copy.py shutil_rmtree.py
shutil_copy2.py shutil_copystat.py shutil_test.py
shutil_copyfile.py shutil_make_archive.py test_new
dy@dy:~/python_test/Day06$ python3 shutil_make_archive.py
dy@dy:~/python_test/Day06$ ls
new_file shutil_copy.py shutil_test.py
old_file shutil_copystat.py test_new
shutil_copy2.py shutil_make_archive.py test_new.tar.gz
shutil_copyfile.py shutil_move.py
shutil_copymode.py shutil_rmtree.py
dy@dy:~/python_test/Day06$ cat shutil_make_archive.py
#!/usr/bin/env python
import shutil
shutil.make_archive("test_new","gztar", root_dir="/home/dy/python_test/Day06")
shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的
import zipfile
# 压缩
z = zipfile.ZipFile('laxi.zip', 'w')
z.write('a.log')
z.write('data.data')
z.close()
# 解压
z = zipfile.ZipFile('laxi.zip', 'r')
z.extractall()
z.close()
import tarfile
# 压缩
tar = tarfile.open('your.tar','w')
tar.add('/Users/wupeiqi/PycharmProjects/bbs2.log', arcname='bbs2.log')
tar.add('/Users/wupeiqi/PycharmProjects/cmdb.log', arcname='cmdb.log')
tar.close()
# 解压
tar = tarfile.open('your.tar','r')
tar.extractall() # 可设置解压地址
tar.close()
shelve模块
shelve模块是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式
将数据写入模块
#!/usr/bin/env python3
import shelve
class Test(object):
def __init__(self, n):
self.n = n
def write_file():
d = shelve.open("shelve_tset")
t1 = Test(123)
t2 = Test(3456)
name = ['aaa', 'sss', 'ddd', 'ffff',]
d["theclass1"] = t1.n
d["theclass2"] = t2.n
d["name"] = name
d.close()
if __name__ == "__main__":
write_file()
读取:
def read_file():
d = shelve.open("shelve_tset")
a = d["name"]
b = d["theclass1"]
print(a, b)
注:shelve与pickle的区别
shelve可以任意顺序的取,而pickle虽然也能多次dump但是在load的时候也只能按照顺序load
XML
XML是实现不同语言或程序之间进行数据交换的协议,XML文件格式如下:
<data>
<country name="Liechtenstein">
<rank updated="yes">2</rank>
<year>2023</year>
<gdppc>141100</gdppc>
<neighbor direction="E" name="Austria" />
<neighbor direction="W" name="Switzerland" />
</country>
<country name="Singapore">
<rank updated="yes">5</rank>
<year>2026</year>
<gdppc>59900</gdppc>
<neighbor direction="N" name="Malaysia" />
</country>
<country name="Panama">
<rank updated="yes">69</rank>
<year>2026</year>
<gdppc>13600</gdppc>
<neighbor direction="W" name="Costa Rica" />
<neighbor direction="E" name="Colombia" />
</country>
</data>
python 读取XML中的数据
#!/usr/bin/env python3
import xml.etree.ElementTree as ET
tree = ET.parse("text.xml")
a = tree.getroot() #获取根节点
print(a.tag) #打印根节点的名字
#遍历XML文档
for i in a:
print("字节点的tag:%s, 字节点的attrib:%s"% (i.tag, a.attrib))
for j in i:
print("字节点的字节点的tag:%s, 字节点的字节点的text:%s" % (j.tag, j.text))
上例中的根节点都有如下方法(子节点也一样)
['__class__', '__copy__', '__deepcopy__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'extend', 'find', 'findall', 'findtext', 'get', 'getchildren', 'getiterator', 'insert', 'items', 'iter', 'iterfind', 'itertext', 'keys', 'makeelement', 'remove', 'set']
python 读取XML中的数据(二)
from xml.etree import ElementTree as ET
str_xml = open('text.xml', 'r').read()
root = ET.XML(str_xml)
for i in root:
print(i.tag)
python 读取XML中的特定数据
#只遍历year节点,类似递归查找,不止在根节点的子节点上
for i in a.iter('year'):
print(i.tag, i.text)
修改和删除xml文档内容
#!/usr/bin/env python3
import xml.etree.ElementTree as ET
tree = ET.parse("text.xml")
root = tree.getroot()
#修改内容
for i in root.iter('year'):
new_year = int(i.text) + 1 #将年份+1
i.text = str(i.text)
i.set("update", "yes") #设置year节点的属性
tree.write("text.xml") #将数据写入文档
#删除节点
for j in root.findall('country'): #找到所有的country节点
rank = int(j.find('rank').text) #将rank数字化
if rank > 50:
root.remove(j) #删除
tree.write("text.xml")
自己创建xml文档
#!/usr/bin/env python3
import xml.etree.ElementTree as ET
new_xml = ET.Element("namelist") #创建根节点
name = ET.SubElement(new_xml, "name", attrib = {"enrolled":"yes"}) #创建子节点及
其属性
age = ET.SubElement(name, "age", attrib = {"checked":"no"}) #子节点的子节点
sex = ET.SubElement(name, "sex",) #子节点的子节点
age.text = '33' #子节点的子节点赋值
sex.text = "nan"
name2 = ET.SubElement(new_xml, "name", attrib = {"enrolled":"no"}, )
age2 = ET.SubElement(name2, "age", )
age2.text = '22'
et = ET.ElementTree(new_xml)#生成XML文档对象
et.write("new_test.xml", encoding = "utf-8", xml_declaration=True)
ET.dump(new_xml) #打印生成的格式
XML模块的其他方法补充
class Element:
"""An XML element.
This class is the reference implementation of the Element interface.
An element's length is its number of subelements. That means if you
want to check if an element is truly empty, you should check BOTH
its length AND its text attribute.
The element tag, attribute names, and attribute values can be either
bytes or strings.
*tag* is the element name. *attrib* is an optional dictionary containing
element attributes. *extra* are additional element attributes given as
keyword arguments.
Example form:
<tag attrib>text<child/>...</tag>tail
"""
当前节点的标签名
tag = None
"""The element's name."""
当前节点的属性
attrib = None
"""Dictionary of the element's attributes."""
当前节点的内容
text = None
"""
Text before first subelement. This is either a string or the value None.
Note that if there is no text, this attribute may be either
None or the empty string, depending on the parser.
"""
tail = None
"""
Text after this element's end tag, but before the next sibling element's
start tag. This is either a string or the value None. Note that if there
was no text, this attribute may be either None or an empty string,
depending on the parser.
"""
def __init__(self, tag, attrib={}, **extra):
if not isinstance(attrib, dict):
raise TypeError("attrib must be dict, not %s" % (
attrib.__class__.__name__,))
attrib = attrib.copy()
attrib.update(extra)
self.tag = tag
self.attrib = attrib
self._children = []
def __repr__(self):
return "<%s %r at %#x>" % (self.__class__.__name__, self.tag, id(self))
def makeelement(self, tag, attrib):
创建一个新节点
"""Create a new element with the same type.
*tag* is a string containing the element name.
*attrib* is a dictionary containing the element attributes.
Do not call this method, use the SubElement factory function instead.
"""
return self.__class__(tag, attrib)
def copy(self):
"""Return copy of current element.
This creates a shallow copy. Subelements will be shared with the
original tree.
"""
elem = self.makeelement(self.tag, self.attrib)
elem.text = self.text
elem.tail = self.tail
elem[:] = self
return elem
def __len__(self):
return len(self._children)
def __bool__(self):
warnings.warn(
"The behavior of this method will change in future versions. "
"Use specific 'len(elem)' or 'elem is not None' test instead.",
FutureWarning, stacklevel=2
)
return len(self._children) != 0 # emulate old behaviour, for now
def __getitem__(self, index):
return self._children[index]
def __setitem__(self, index, element):
# if isinstance(index, slice):
# for elt in element:
# assert iselement(elt)
# else:
# assert iselement(element)
self._children[index] = element
def __delitem__(self, index):
del self._children[index]
def append(self, subelement):
为当前节点追加一个子节点
"""Add *subelement* to the end of this element.
The new element will appear in document order after the last existing
subelement (or directly after the text, if it's the first subelement),
but before the end tag for this element.
"""
self._assert_is_element(subelement)
self._children.append(subelement)
def extend(self, elements):
为当前节点扩展 n 个子节点
"""Append subelements from a sequence.
*elements* is a sequence with zero or more elements.
"""
for element in elements:
self._assert_is_element(element)
self._children.extend(elements)
def insert(self, index, subelement):
在当前节点的子节点中插入某个节点,即:为当前节点创建子节点,然后插入指定位置
"""Insert *subelement* at position *index*."""
self._assert_is_element(subelement)
self._children.insert(index, subelement)
def _assert_is_element(self, e):
# Need to refer to the actual Python implementation, not the
# shadowing C implementation.
if not isinstance(e, _Element_Py):
raise TypeError('expected an Element, not %s' % type(e).__name__)
def remove(self, subelement):
在当前节点在子节点中删除某个节点
"""Remove matching subelement.
Unlike the find methods, this method compares elements based on
identity, NOT ON tag value or contents. To remove subelements by
other means, the easiest way is to use a list comprehension to
select what elements to keep, and then use slice assignment to update
the parent element.
ValueError is raised if a matching element could not be found.
"""
# assert iselement(element)
self._children.remove(subelement)
def getchildren(self):
获取所有的子节点(废弃)
"""(Deprecated) Return all subelements.
Elements are returned in document order.
"""
warnings.warn(
"This method will be removed in future versions. "
"Use 'list(elem)' or iteration over elem instead.",
DeprecationWarning, stacklevel=2
)
return self._children
def find(self, path, namespaces=None):
获取第一个寻找到的子节点
"""Find first matching element by tag name or path.
*path* is a string having either an element tag or an XPath,
*namespaces* is an optional mapping from namespace prefix to full name.
Return the first matching element, or None if no element was found.
"""
return ElementPath.find(self, path, namespaces)
def findtext(self, path, default=None, namespaces=None):
获取第一个寻找到的子节点的内容
"""Find text for first matching element by tag name or path.
*path* is a string having either an element tag or an XPath,
*default* is the value to return if the element was not found,
*namespaces* is an optional mapping from namespace prefix to full name.
Return text content of first matching element, or default value if
none was found. Note that if an element is found having no text
content, the empty string is returned.
"""
return ElementPath.findtext(self, path, default, namespaces)
def findall(self, path, namespaces=None):
获取所有的子节点
"""Find all matching subelements by tag name or path.
*path* is a string having either an element tag or an XPath,
*namespaces* is an optional mapping from namespace prefix to full name.
Returns list containing all matching elements in document order.
"""
return ElementPath.findall(self, path, namespaces)
def iterfind(self, path, namespaces=None):
获取所有指定的节点,并创建一个迭代器(可以被for循环)
"""Find all matching subelements by tag name or path.
*path* is a string having either an element tag or an XPath,
*namespaces* is an optional mapping from namespace prefix to full name.
Return an iterable yielding all matching elements in document order.
"""
return ElementPath.iterfind(self, path, namespaces)
def clear(self):
清空节点
"""Reset element.
This function removes all subelements, clears all attributes, and sets
the text and tail attributes to None.
"""
self.attrib.clear()
self._children = []
self.text = self.tail = None
def get(self, key, default=None):
获取当前节点的属性值
"""Get element attribute.
Equivalent to attrib.get, but some implementations may handle this a
bit more efficiently. *key* is what attribute to look for, and
*default* is what to return if the attribute was not found.
Returns a string containing the attribute value, or the default if
attribute was not found.
"""
return self.attrib.get(key, default)
def set(self, key, value):
为当前节点设置属性值
"""Set element attribute.
Equivalent to attrib[key] = value, but some implementations may handle
this a bit more efficiently. *key* is what attribute to set, and
*value* is the attribute value to set it to.
"""
self.attrib[key] = value
def keys(self):
获取当前节点的所有属性的 key
"""Get list of attribute names.
Names are returned in an arbitrary order, just like an ordinary
Python dict. Equivalent to attrib.keys()
"""
return self.attrib.keys()
def items(self):
获取当前节点的所有属性值,每个属性都是一个键值对
"""Get element attributes as a sequence.
The attributes are returned in arbitrary order. Equivalent to
attrib.items().
Return a list of (name, value) tuples.
"""
return self.attrib.items()
def iter(self, tag=None):
在当前节点的子孙中根据节点名称寻找所有指定的节点,并返回一个迭代器(可以被for循环)。
"""Create tree iterator.
The iterator loops over the element and all subelements in document
order, returning all elements with a matching tag.
If the tree structure is modified during iteration, new or removed
elements may or may not be included. To get a stable set, use the
list() function on the iterator, and loop over the resulting list.
*tag* is what tags to look for (default is to return all elements)
Return an iterator containing all the matching elements.
"""
if tag == "*":
tag = None
if tag is None or self.tag == tag:
yield self
for e in self._children:
yield from e.iter(tag)
# compatibility
def getiterator(self, tag=None):
# Change for a DeprecationWarning in 1.4
warnings.warn(
"This method will be removed in future versions. "
"Use 'elem.iter()' or 'list(elem.iter())' instead.",
PendingDeprecationWarning, stacklevel=2
)
return list(self.iter(tag))
def itertext(self):
在当前节点的子孙中根据节点名称寻找所有指定的节点的内容,并返回一个迭代器(可以被for循环)。
"""Create text iterator.
The iterator loops over the element and all subelements in document
order, returning all inner text.
"""
tag = self.tag
if not isinstance(tag, str) and tag is not None:
return
if self.text:
yield self.text
for e in self:
yield from e.itertext()
if e.tail:
yield e.tail
configparser模块
configparser用于处理特定格式的文件,其本质上是利用open来操作文件。
生成一个新的配置文件
#!/usr/bin/env python3
# 生成一个新文档
import configparser
config = configparser.ConfigParser()
config["DEFAULT"] = {
'ServerAliveInterval':'45',
'Compression':'yes',
'CompressionLevel':'9',
}
#DEFAULT 是全局配置,在下面的所有节点中都生效
config['bitbucket.org'] = {} #创建一个空节点
config['bitbucket.org']['User'] = 'xiaowang' #在节点中添加字段
config['topsecret.server.com'] = {}
topsecret = config['topsecret.server.com']
topsecret['Host Port'] = '50022' #这里必须是字符,不是别数字
topsecret['ForwardX11'] = 'no'
config["DEFAULT"]["ForwardX11"] = "yes" #添加全局配置
with open('example.ini', 'w') as configfile:
config.write(configfile)
~
获取文件内所有的节点
#!/usr/bin/env python3
import configparser
#获取所有节点
config = configparser.ConfigParser()
config.read('example.ini', encoding='utf-8')
ret = config.sections()
print(ret)
dy@dy:~/python_test/Day06/configparser$ python3 configparser_02.py
['bitbucket.org', 'topsecret.server.com']
#DEFAULT是全局配置,不再其中
获取指定节点下所有的键值对
#!/usr/bin/env python3
#获取节点下的k,v
import configparser
config = configparser.ConfigParser()
config.read('example.ini', encoding='utf-8')
ret = config.items('bitbucket.org')
print(ret)
dy@dy:~/python_test/Day06/configparser$ python3 configparser_03.py
[('compression', 'yes'), ('serveraliveinterval', '45'), ('compressionlevel', '9'), ('forwardx11', 'yes'), ('user', 'xiaowang')]
获取指定节点下所有的建
#!/usr/bin/env python3
#制定节点下所有的键
import configparser
config = configparser.ConfigParser()
config.read('example.ini', encoding='utf-8')
ret = config.options('topsecret.server.com') #获取该节点所有的选项
print(ret)
dy@dy:~/python_test/Day06/configparser$ python3 configparser_04.py
['host port', 'forwardx11', 'compression', 'serveraliveinterval', 'compressionlevel']
获取指定节点下指定key的值
#!/us/bin/env pthon3
# 获取指定节点下value的值
import configparser
config = configparser.ConfigParser()
config.read('example.ini', encoding='utf-8')
ret1 = config.get('topsecret.server.com', 'host port')
ret2 = config.get('topsecret.server.com', 'forwardx11')
print('v1:',ret1)
print('v2:',ret2)
dy@dy:~/python_test/Day06/configparser$ python3 configparser_05.py
v1: 50022
v2: no
有关节点的一些操作
检查指定节点是否存在
#!/usr/bin/env python3
#检查节点是否存在
import configparser
config = configparser.ConfigParser()
config.read('example.ini', encoding='utf-8')
check1 = config.has_section('aaa')
print('check1:',check1)
check2 = config.has_section('bitbucket.org')
print('check2:',check2)
dy@dy:~/python_test/Day06/configparser$ python3 configparser_06.py
check1: False
check2: True
添加指定节点
#!/usr/bin/env python3
#添加节点
import configparser
config = configparser.ConfigParser()
config.read('example.ini', encoding='utf-8')
config.add_section("test_section")
config.write(open('example.ini', 'w'))
#节点已存在的时候会报错
删除指定节点
#!/usr/bin/env python3
#删除指定节点
import configparser
config = configparser.ConfigParser()
config.read('example.ini', encoding='utf-8')
config.remove_section('test_section')
config.write(open('example.ini', 'w'))
有关键值对的一些操作
检查执行选项内的key
#!/usr/bin/env python3
import configparser
#检查指定的选项内的key是否存在
config = configparser.ConfigParser()
config.read('example.ini', encoding='utf-8')
check1 = config.has_option('topsecret.server.com', 'forwardx11')
print('check1:', check1)
check2 = config.has_option('topsecret.server.com', 'aaa')
print('check2:', check2)
dy@dy:~/python_test/Day06/configparser$ python3 configparser_09.py
check1: True
check2: False
删除指定选项中的执行的key
#!/usr/bin/env python3
#删除执行选项下的key
import configparser
config = configparser.ConfigParser()
config.read('example.ini', encoding='utf-8')
config.remove_option('topsecret.server.com', 'forwardx11')
config.write(open('example.ini', 'w'))
在指定的选项中修改key的value(没有则创建)
#!/usr/bin/env python3
import configparser
config = configparser.ConfigParser()
config.read('example.ini', encoding='utf-8')
config.set('topsecret.server.com', 'test1','test_value1')
config.write(open('example.ini', 'w'))
hashlib模块
用于加密相关的操作,代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
md5部分
#!/usr/bin/env python
import hashlib
text = hashlib.md5()
text.update(bytes('xiaoming', encoding="utf-8")) #将字符串加密
print(text.hexdigest()) #显示MD5值
print(text.digest()) #显示二进制的值
a = hashlib.md5()
a.update(b"xiaolan")
print(a.digest()) #显示加密的二进制格式
print(a.hexdigest()) #显示MD5值
dy@dy:~/python_test/Day06/hashlib$ python3 hashlib_md5.py
97304531204ef7431330c20427d95481
b"\x970E1 N\xf7C\x130\xc2\x04'\xd9T\x81"
b'\xda]\x9a\xcc\x91\xd6b\x8en\x1cL\x99\xfe\x80\x89\x13'
da5d9acc91d6628e6e1c4c99fe808913
sha加密
sha1
#!/usr/bin/env python3
import hashlib
#sha1加密算法
text = hashlib.sha1()
text.update(b"xiaowang")
print(text.hexdigest())
sha256
import hashlib
text = hashlib.sha256()
text.update(b"xiaowang")
print(text.hexdigest())
sha384
import hashlib
text = hashlib.sha384()
text.update(b"xiaowang")
print(text.hexdigest())
sha512
import hashlib
text = hashlib.sha512()
text.update(b"xiaowang")
print(text.hexdigest())
其他注意的地方
以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。所以,有必要对加密算法中添加自定义key再来做加密
#!/usr/bin/env python3
import hashlib
text = hashlib.md5(b"12345")
text.update(b"xiaowang")
print(text.hexdigest())
python内置还有一个 hmac 模块,它内部对我们创建 key 和 内容 进行进一步的处理然后再加密
#!/usr/bin/env python3
import hmac
h = hmac.new(b"45323")
h.update(b"asdasd")
print(h.hexdigest())
subprocess模块
执行shell命令的相关的模块和函数的功能均在 subprocess 模块中实现,并提供了更丰富的功能。
执行命令并将结果显示出来,返回命令的执行状带
call
>>> import subprocess
>>> ret = subprocess.call(['ls', '-l'], shell=False)
总用量 16
-rw-r--r-- 1 dy dy 100 5月 24 10:56 hashlib_hmac.py
-rw-r--r-- 1 dy dy 117 5月 24 10:50 hashlib_md52.py
-rw-r--r-- 1 dy dy 337 5月 24 09:58 hashlib_md5.py
-rw-r--r-- 1 dy dy 127 5月 24 10:10 hashlib_sha1.py
>>> ret = subprocess.call(['ls', '-l'], shell=True)
hashlib_hmac.py hashlib_md5.py
hashlib_md52.py hashlib_sha1.py
#不带参数的时候不需要列表
>>> ret = subprocess.call('ls', shell=True)
hashlib_hmac.py hashlib_md5.py
hashlib_md52.py hashlib_sha1.py
>>> ret = subprocess.call('ls', shell=False)
hashlib_hmac.py hashlib_md5.py
hashlib_md52.py hashlib_sha1.py
#返回的结果时命令的执行状态,不是命令执行的结果
>>> ret
0
check_call
执行命令,如果执行状态码是0,则返回0,否则抛出异常
>>> subprocess.check_call(['ls', '-l'])
总用量 16
-rw-r--r-- 1 dy dy 100 5月 24 10:56 hashlib_hmac.py
-rw-r--r-- 1 dy dy 117 5月 24 10:50 hashlib_md52.py
-rw-r--r-- 1 dy dy 337 5月 24 09:58 hashlib_md5.py
-rw-r--r-- 1 dy dy 127 5月 24 10:10 hashlib_sha1.py
0
>>> subprocess.check_call(['lsaa', '-l'])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.5/subprocess.py", line 266, in check_call
retcode = call(*popenargs, **kwargs)
File "/usr/lib/python3.5/subprocess.py", line 247, in call
with Popen(*popenargs, **kwargs) as p:
File "/usr/lib/python3.5/subprocess.py", line 676, in __init__
restore_signals, start_new_session)
File "/usr/lib/python3.5/subprocess.py", line 1282, in _execute_child
raise child_exception_type(errno_num, err_msg)
FileNotFoundError: [Errno 2] No such file or directory: 'lsaa'
check_output
执行命令,如果状态码是0,则返回执行结果,否则抛出异常
>>> a = subprocess.check_output(["echo","hi xiao wang"], shell=False)
>>> a
b'hi xiao wang\n'
subprocess.Popen()
用于执行复杂的系统命令
参数:
args:shell命令,可以是字符串或者序列类型(如:list,元组)
bufsize:指定缓冲。0 无缓冲,1 行缓冲,其他 缓冲区大小,负值 系统缓冲
stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
preexec_fn:只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用
close_sfs:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会继承父进程的输入、输出、错误管道。所以不能将close_fds设置为True同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。
shell:同上
cwd:用于设置子进程的当前目录
env:用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。
universal_newlines:不同系统的换行符不同,True -> 同意使用 \n
startupinfo与createionflags只在windows下有效,将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等。
执行普通命令
>>> import subprocess
>>> a = subprocess.Popen(['mkdir', 'test_1'])
>>> print(a)
<subprocess.Popen object at 0x7f6ad759dc50>
>>> b = subprocess.Popen('mkdir test_2')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.5/subprocess.py", line 676, in __init__
restore_signals, start_new_session)
File "/usr/lib/python3.5/subprocess.py", line 1282, in _execute_child
raise child_exception_type(errno_num, err_msg)
FileNotFoundError: [Errno 2] No such file or directory: 'mkdir test_2'
>>> b = subprocess.Popen('mkdir test_2', shell=True)
>>>
#指定命令执行的目录
>>> a = subprocess.Popen(['mkdir', 'test_3'], cwd='/home/dy')
执行复杂的命令
#!/usr/bin/env python3
#执行复杂的命令,例如需要交互的脚本,shell等
import subprocess
#设置管道,捕获子进程的输入输出
obj = subprocess.Popen(['python'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
#向子进程输入命令
obj.stdin.write("print('test_1')\n")
obj.stdin.write("print('test_2')")
obj.stdin.close()
cmd_out = obj.stdout.read()
obj.stdout.close()
cmd_error = obj.stderr.read()
obj.stderr.close()
print(cmd_out)
print(cmd_error)
dy@dy:~/python_test/Day06/subprocess$ python3 subprocess_test01.py
test_1
test_2
#!/usr/bin/env python3
import subprocess
obj = subprocess.Popen(['python'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
obj.stdin.write("print('test_22')\n")
obj.stdin.write("print('yes')")
#将输出和错误组合成一个元祖输出,第一个元素的输出,第二个时错误
out_error_list = obj.communicate()
print(out_error_list)
dy@dy:~/python_test/Day06/subprocess$ python3 subprocess_test02.py
('test_22\nyes\n', '')
#!/usr/bin/env pyton3
import subprocess
obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
#输出结果错误元组的变形,只接收二进制字符串
out_error_list = obj.communicate(b"print('hello word')")
print(out_error_list)
dy@dy:~/python_test/Day06/subprocess$ python3 subprocess_test03.py
(b'hello word\n', b'')
一些其他的用法
#接收字符串格式的命令,返回元祖形式,第一个元素时执行状告太,第二个时命令结果
>>> subprocess.getstatusoutput("ls /bin/ls")
(0, '/bin/ls')
>>>
#接收字符串格式命令,并返回结果
>>> a = subprocess.getoutput("ls /home")
>>> print(a)
dy
#执行命令并返回结果,注意时返回结果,不是打印
>>> a = subprocess.check_output(['ls', '-l', '/home'])
>>> print(a)
b'\xe6\x80\xbb\xe7\x94\xa8\xe9\x87\x8f 4\ndrwxr-xr-x 35 dy dy 4096 5\xe6\x9c\x88 25 11:29 dy\n'
>>>
#run的使用
>>> a = subprocess.run(['ls', '-l'])
总用量 12
-rw-r--r-- 1 dy dy 531 5月 25 10:33 subprocess_test01.py
-rw-r--r-- 1 dy dy 396 5月 25 10:46 subprocess_test02.py
-rw-r--r-- 1 dy dy 291 5月 25 11:28 subprocess_test03.py
>>> print(a)
CompletedProcess(args=['ls', '-l'], returncode=0)
>>>
>>> a = subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
>>> print(a)
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0, stdout=b'crw-rw-rw- 1 root root 1, 3 5\xe6\x9c\x88 25 08:49 /dev/null\n')
>>>
logging模块
很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误、警告等信息输出,python的logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,logging的日志可以分为 debug(), info(), warning(), error() and critical() 5个级别。
简单的用法
#!/usr/bin/env python3
import logging
logging.warning("Test warning info")
logging.critical("Tom is dead")
dy@dy:~/python_test/Day06/logging$ python3 logging_tset01.py
WARNING:root:Test warning info
CRITICAL:root:Tom is dead
日志的级别,越往下级别越高,越严重
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.
把日志写道文件中
#!/usr/bin/env python3
#将日志写入文件
import logging
#设置记录日志写入文件的级别,只有级别大于等于INFO的日志才会写道文件中
#format设置日志格式,datefmt设置日期格式
logging.basicConfig(filename='example.log', level=logging.INFO, format='%(asctime)s %(message)s', datefmt='%Y-%d-%m %I:%M:%S %p')
logging.debug('Test debug info')
logging.info("Test info info")
logging.warning("Test warning info")
dy@dy:~/python_test/Day06/logging$ cat example.log
2017-25-05 03:56:25 PM Test info info
2017-25-05 03:56:25 PM Test warning info
日志格式参数
%(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 用户输出的消息
将日志输出的同时,还能写入文件
Python 使用logging模块记录日志涉及四个主要类,使用官方文档中的概括最为合适:
logger提供了应用程序可以直接使用的接口;
handler将(logger创建的)日志记录发送到合适的目的输出;
filter提供了细度设备来决定输出哪条日志记录;
formatter决定日志记录的最终输出格式。
logger
每个程序在输出信息之前都要获得一个Logger。Logger通常对应了程序的模块名,比如聊天工具的图形界面模块可以这样获得它的Logger:
LOG=logging.getLogger(”chat.gui”)
而核心模块可以这样:
LOG=logging.getLogger(”chat.kernel”)
Logger.setLevel(lel):指定最低的日志级别,低于lel的级别将被忽略。debug是最低的内置级别,critical为最高
Logger.addFilter(filt)、Logger.removeFilter(filt):添加或删除指定的filter
Logger.addHandler(hdlr)、Logger.removeHandler(hdlr):增加或删除指定的handler
Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical():可以设置的日志级别
handler
handler对象负责发送相关的信息到指定目的地。Python的日志系统有多种Handler可以使用。有些Handler可以把信息输出到控制台,有些Logger可以把信息输出到文件,还有些 Handler可以把信息发送到网络上。如果觉得不够用,还可以编写自己的Handler。可以通过addHandler()方法添加多个多handler
Handler.setLevel(lel):指定被处理的信息级别,低于lel级别的信息将被忽略
Handler.setFormatter():给这个handler选择一个格式
Handler.addFilter(filt)、Handler.removeFilter(filt):新增或删除一个filter对象
每个Logger可以附加多个Handler。接下来我们就来介绍一些常用的Handler:
1) logging.StreamHandler
使用这个Handler可以向类似与sys.stdout或者sys.stderr的任何文件对象(file object)输出信息。它的构造函数是:
StreamHandler([strm])
其中strm参数是一个文件对象。默认是sys.stderr
2) logging.FileHandler
和StreamHandler类似,用于向一个文件输出日志信息。不过FileHandler会帮你打开这个文件。它的构造函数是:
FileHandler(filename[,mode])
filename是文件名,必须指定一个文件名。
mode是文件的打开方式。参见Python内置函数open()的用法。默认是’a’,即添加到文件末尾。
3) logging.handlers.RotatingFileHandler
这个Handler类似于上面的FileHandler,但是它可以管理文件大小。当文件达到一定大小之后,它会自动将当前日志文件改名,然后创建 一个新的同名日志文件继续输出。比如日志文件是chat.log。当chat.log达到指定的大小之后,RotatingFileHandler自动把 文件改名为chat.log.1。不过,如果chat.log.1已经存在,会先把chat.log.1重命名为chat.log.2。。。最后重新创建 chat.log,继续输出日志信息。它的构造函数是:
RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]])
其中filename和mode两个参数和FileHandler一样。
maxBytes用于指定日志文件的最大文件大小。如果maxBytes为0,意味着日志文件可以无限大,这时上面描述的重命名过程就不会发生。
backupCount用于指定保留的备份文件的个数。比如,如果指定为2,当上面描述的重命名过程发生时,原有的chat.log.2并不会被更名,而是被删除。
4) logging.handlers.TimedRotatingFileHandler
这个Handler和RotatingFileHandler类似,不过,它没有通过判断文件大小来决定何时重新创建日志文件,而是间隔一定时间就 自动创建新的日志文件。重命名的过程与RotatingFileHandler类似,不过新的文件不是附加数字,而是当前时间。它的构造函数是:
TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]])
其中filename参数和backupCount参数和RotatingFileHandler具有相同的意义。
interval是时间间隔。
when参数是一个字符串。表示时间间隔的单位,不区分大小写。它有以下取值:
S 秒
M 分
H 小时
D 天
W 每星期(interval==0时代表星期一)
midnight 每天凌晨
#!/usr/bin/env python3
#在显示屏幕的同时将日志写入文件
import logging
#创建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 level to warning
fh = logging.FileHandler("testlog.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 ogger
logger.addHandler(ch)
logger.addHandler(fh)
#添加日志
logger.debug("This is debug info")
logger.info("This is info info")
logger.warn('This is warn info')
logger.error("This is error info")
logger.critical("This is critical info")
dy@dy:~/python_test/Day06/logging$ python3 logging_tset03.py
2017-05-26 10:33:49,392 - Test-log - DEBUG - This is debug info
2017-05-26 10:33:49,392 - Test-log - INFO - This is info info
2017-05-26 10:33:49,393 - Test-log - WARNING - This is warn info
2017-05-26 10:33:49,393 - Test-log - ERROR - This is error info
2017-05-26 10:33:49,393 - Test-log - CRITICAL - This is critical info
文件自动截断例子
dy@dy:~/python_test/Day06/logging$ cat logging_tset04.py
#!/usr/bin/env python3
#文件自动截断例子
import logging
from logging import handlers
logger = logging.getLogger(__name__)
log_file = "Test2log.log"
fh = handlers.TimedRotatingFileHandler(filename=log_file,when='s',interval=5,backupCount=3)
formatter = logging.Formatter('%(asctime)s %(module)s:%(lineno) %(message)s')
fh.setFormatter(formatter)
logger.addHandler(fh)
logger.warning("test1")
logger.warning("test2")
logger.warning("test3")
logger.warning("test4")
dy@dy:~/python_test/Day06/logging$ python3 logging_tset04.py
dy@dy:~/python_test/Day06/logging$ cat Test2log.log
2017-05-26 10:45:09,781 logging_tset04:%(message)s
2017-05-26 10:45:09,781 logging_tset04:%(message)s
2017-05-26 10:45:09,781 logging_tset04:%(message)s
2017-05-26 10:45:09,781 logging_tset04:%(message)s
random模块
#!/usr/bin/env python3
import random
print(random.random())
print(random.randint(1,2))
print(random.randrange(1,10))
dy@dy:~/python_test/Day06/random$ python3 random_test01.py
0.19451261617775595
2
4
#!/usr/bin/env python3
import random
checkcode = ''
for i in range(4):
current = random.randrange(0,4)
if current != i:
temp = chr(random.randint(65,90))
else:
temp = random.randint(0,9)
checkcode += str(temp)
print(checkcode)
dy@dy:~/python_test/Day06/random$ python3 random_test02.py
CWP7
requsets模块
Python标准库中提供了:urllib等模块以供Http请求,但是,它的 API 太渣了。它是为另一个时代、另一个互联网所创建的。它需要巨量的工作,甚至包括各种方法覆盖,来完成最简单的任务。
urllib
发送get请求
#!/usr/bi/env python3
import urllib.request
f = urllib.request.urlopen('http://www.webxml.com.cn//webservices/qqOnlineWebService.asmx/qqCheckOnline?qqCode=424662508')
result = f.read().decode('utf-8')
发送携带请求头的GET请求
#!/usr/bin/env python3
import urllib.request
req = urllib.request.Request('http://www.example.com/')
req.add_header('Referer', 'http://www.python.org/')
r = urllib.request.urloprn(req)
result = f.read().decode('utf-8')
注:更多见Python官方文档:https://docs.python.org/3.5/library/urllib.request.html#module-urllib.request
Requests 是使用 Apache2 Licensed 许可证的 基于Python开发的HTTP 库,其在Python内置模块的基础上进行了高度的封装,从而使得Pythoner进行网络请求时,变得美好了许多,使用Requests可以轻而易举的完成浏览器可有的任何操作。
requests
安装模块
pip3 install requests
使用模块
get请求
无参数实例
#!/usr/bin/env python3
import requests
ret = requests.get('https://github.com/timeline.json')
print(ret.url)
print(ret.text)
dy@dy:~/python_test/Day06/requests$ python3 requests_test01.py
https://github.com/timeline.json
{"message":"Hello there, wayfaring stranger. If you’re reading this then you probably didn’t see our blog post a couple of years back announcing that this API would go away: http://git.io/17AROg Fear not, you should be able to get what you need from the shiny new Events API instead.","documentation_url":"https://developer.github.com/v3/activity/events/#list-public-events"}
有参数实例
#!/usr/bin/env python3
import requests
payload = {'key1':'value1', 'key2':'value2'}
ret = requests.get("http://httpbin.org/get", params=payload)
print(ret.url)
print(ret.text)
dy@dy:~/python_test/Day06/requests$ python3 requests_test02.py
http://httpbin.org/get?key2=value2&key1=value1
{
"args": {
"key1": "value1",
"key2": "value2"
},
"headers": {
"Accept": "*/*",
"Connection": "close",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.10.0"
},
"origin": "124.127.119.165",
"url": "http://httpbin.org/get?key2=value2&key1=value1"
}
post请求
基本post实例
#!/usr/bin/env python3
import requests
payload = {'key1':'value1', 'key2':'value2'}
ret = requests.post("http://httpbin.org/post",data=payload)
print(ret.text)
dy@dy:~/python_test/Day06/requests$ python3 requests_test03.py
{
"args": {},
"data": "",
"files": {},
"form": {
"key1": "value1",
"key2": "value2"
},
"headers": {
"Accept": "*/*",
"Connection": "close",
"Content-Length": "23",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.10.0"
},
"json": null,
"origin": "58.30.135.208",
"url": "http://httpbin.org/post"
}
发送请求头和数据实例
#!/usr/bin/env python3
import requests
import json
url = 'https://api.github.com/some/endpoint'
payload = {'some':'data'}
headers = {'content-ytpe':'application/json'}
ret = requests.post(url, data=json.dumps(payload), headers=headers)
print(ret.text)
print(ret.cookies)
dy@dy:~/python_test/Day06/requests$ python3 requests_test04.py
{"message":"Not Found","documentation_url":"https://developer.github.com/v3"}
<RequestsCookieJar[]>
更多requests模块相关的文档见:http://cn.python-requests.org/zh_CN/latest/
Http请求和XML实例
实例:检测QQ帐号是否在线
#!/usr/bin/env python3
import urllib
import requests
from xml.etree import ElementTree as ET
#使用内置模块urllib发送HTTP请求,或者XML格式内容
"""
f = urllib.requset.urlopen('http://www.webxml.com.cn//webservices/qqOnlineWebService.asmx/qqCheckOnline?qqCode=424662508')
result = f.read().decode('utf-8')
"""
#使用第三方模块requests发送http请求,或者XML格式内容
r = requests.get('http://www.webxml.com.cn//webservices/qqOnlineWebService.asmx/qqCheckOnline?qqCode=424662508')
result = t.text
#解析XML格式内容
node = ET.XML(result)
#获取内容
if node.text == 'Y':
print("在线")
else:
print("离线")
paramiko模块
paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作,值得一说的是,fabric和ansible内部的远程管理就是使用的paramiko来现实。
下载安装
pycrypto,由于 paramiko 模块内部依赖pycrypto,所以先下载安装pycrypto
pip3 install pycrypto
pip3 install paramiko
模块使用
执行命令,用户名+密码
#!/usr/bin/env python3
#执行命令,用户名+密码
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.101.2', 22, "root", '111111')
stdin, stdout, stderr = ssh.exec_command('df')
print(stdout.read())
ssh.close()
dy@dy:~/python_test/Day06/paramiko$ python3 paramiko_test01.py
b'Filesystem 1K-blocks Used Available Use% Mounted on\n/dev/mapper/vg_dy-lv_root 18134344 778436 16434720 5% /\ntmpfs 502204 0 502204 0% /dev/shm\n/dev/sda1 495844 33474 436770 8% /boot\n'
执行命令,密钥
#!/usr/bin/env python3
#执行命令,密钥
import paramiko
private_key_path = '/home/auto/.ssh/id_rsa'
key = paramiko.RSAKey.from_private_key_file(private_key_path)
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.101.2', 22, 'root', '111111')
stdin, stdout, stderr = ssh.exec_command('df')
print(stdout.read())
ssh.close()
上传或下载文件,用户名+密码
#!/sur/bin/env python3
#上传或下载文件,用户名+密码
import paramiko
import os,sys
t = paramiko.Transport(('192.168.101.2', 22))
t.connect(username='root',password='111111')
sftp = paramiko.SFTPClient.from_transport(t)
sftp.put('/tmp/test.py','/tmp/test.py') #第一个参数是本地上传的文件,第二个参数>时上传后目标机器保存的文件
t.close()
下载或上传文件,密钥
#!/usr/bin/env python3
#下载或上传文件,密钥
import paramiko
pravie_key_path = '/home/auto/.ssh/id_rsa'
key = paramiko.RSAKey.from+private_key_file(pravie_key_path)
t = paramiko.Transport(('192.168.101.2', 22))
t.connect(username='root',pkey=key)
sftp = paramiko.SFTPClient.from_transport(t)
sftp.put('/tmp/test2.py', '/tmp/test2.py')
t.close()
time模块
时间相关的操作,时间有三种表示方式:
时间戳 1970年1月1日之后的秒,即:time.time()
格式化的字符串 2014-11-11 11:11, 即:time.strftime(‘%Y-%m-%d’)
结构化时间 元组包含了:年、日、星期等… time.struct_time 即:time.localtime()
>>> import time
>>> print(time.time())
1496212701.906987
>>> print(time.mktime(time.localtime()))
1496212735.0
>>> print(time.gmtime()) #可加时间戳参数
time.struct_time(tm_year=2017, tm_mon=5, tm_mday=31, tm_hour=6, tm_min=41, tm_sec=20, tm_wday=2, tm_yday=151, tm_isdst=0)
>>> print(time.localtime())
time.struct_time(tm_year=2017, tm_mon=5, tm_mday=31, tm_hour=14, tm_min=42, tm_sec=12, tm_wday=2, tm_yday=151, tm_isdst=0) #可加时间戳参数
>>> print(time.strptime('2014-11-11', '%Y-%m-%d'))
time.struct_time(tm_year=2014, tm_mon=11, tm_mday=11, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=1, tm_yday=315, tm_isdst=-1)
>>> print(time.strftime('%Y-%m-%d')) #默认当前时间
2017-05-31
>>> print(time.strftime('%y-%m-%d', time.localtime())) #默认当前时间
17-05-31
>>> print(time.asctime())
Wed May 31 14:53:10 2017
>>> print(time.asctime(time.localtime()))
Wed May 31 14:53:40 2017
>>> print(time.ctime(time.time()))
Wed May 31 14:54:12 2017
import datetime
datetime.date:表示日期的类。常用的属性有year, month, day
datetime.time:表示时间的类。常用的属性有hour, minute, second, microsecond
datetime.datetime:表示日期时间
datetime.timedelta:表示时间间隔,即两个时间点之间的长度
timedelta([days[, seconds[, microseconds[, milliseconds[, minutes[, hours[, weeks]]]]]]])
strftime("%Y-%m-%d")
>>> import datetime
>>> print(datetime.datetime.now())
2017-05-31 14:56:02.250685
>>> print(datetime.datetime.now() - datetime.timedelta(days=5))
2017-05-26 14:57:18.928079
格式化占位符
%Y Year with century as a decimal number.
%m Month as a decimal number [01,12].
%d Day of the month as a decimal number [01,31].
%H Hour (24-hour clock) as a decimal number [00,23].
%M Minute as a decimal number [00,59].
%S Second as a decimal number [00,61].
%z Time zone offset from UTC.
%a Locale's abbreviated weekday name.
%A Locale's full weekday name.
%b Locale's abbreviated month name.
%B Locale's full month name.
%c Locale's appropriate date and time representation.
%I Hour (12-hour clock) as a decimal number [01,12].
%p Locale's equivalent of either AM or PM.