人生苦短,我用Python04:模块

时间:July 12, 2017 分类:

目录:

Python模块

什么是模块

模块和函数的目的是一样的,都是为了提高程序的重复可用性。

如何导入模块

最简单的导入方式

import a        #引入模块a

成功导入后就可以使用a模块中对象或方法。

更多模块导入方式

import a as b   #引入模块a,并将模块a重命名为b,在调用的时候直接调用b即可
from a import b #从模块a中引入b对象,在调用a中的b对象的时候,不需要说明模块,直接使用b即可,而不是a.b
from a import * #从模块a中引入所有对象

if __name__ == "__main__"的作用

有句经典话总结了这个的作用——"Make a script both importable and executable",意思就是说让你写的脚本模块既可以导入到别的模块中用,另外该模块自己也可执行。

执行模块

[root@why ~]# vi module.py
[root@why ~]# cat module.py 
def main():
  print "This is %s"%__name__
if __name__ == '__main__':
  main()
[root@why ~]# python module.py 
This is __main__

可以看到这个main()方法被执行了,因为__name__为"__main__"

导入模块

[root@why ~]# vi testmodule.py
[root@why ~]# cat testmodule.py 
import module
module.main()
[root@why ~]# python testmodule.py 
This is module

在导入的时候,main没有被执行,而是用过我们执行,此时__name__为module

模块搜索路径

  1. 程序当前所在路径
  2. 标准库安装路径
  3. 操作系统环境变量PYTHONPATH所包含的路径

如何成为一个库

可以将功能相似的模块放在同一个文件夹(比如说this_dir)中,构成一个模块包。通过

import this_dir.module

引入this_dir文件夹中的module模块。

该文件夹中必须包含一个__init__.py的文件,提醒Python,该文件夹为一个模块包。__init__.py可以是一个空文件。

如何安装一个模块

  1. 把py文件直接拷贝到模块的搜索路径,当然要有py文件,并且保证版本问题
  2. 源码安装,需要提前安装setuptools
  3. easy_install或pip方式安装

常用模块

time模块

等待5s

time.sleep(5) 单位为秒

进度条

from __future__ import division
import sys,time

for i in range(31):
    sys.stdout.write('\r')
    sys.stdout.write('%s%% |%s' % (int(i/30*100),int(i/30*100)*'*'))
    sys.stdout.flush()
    time.sleep(0.2)

执行结果

当前时间戳

>>> import time
>>> time.time()
1498313313.0996261

当前时间(由时间戳转化为时间)

>>> time.ctime()
'Sat Jun 24 22:08:39 2017'
>>> time.ctime(time.time())
'Sat Jun 24 22:09:03 2017'
>>> time.ctime(time.time()-86400)
'Fri Jun 23 22:09:10 2017'

时间戳转化为时间

>>> time.gmtime(time.time())                        #转换为UTC时间
time.struct_time(tm_year=2017, tm_mon=6, tm_mday=24, tm_hour=14, tm_min=37, tm_sec=19, tm_wday=5, tm_yday=175, tm_isdst=0)
>>> time.localtime(time.time())                     #转换为当前时区时间
time.struct_time(tm_year=2017, tm_mon=6, tm_mday=24, tm_hour=22, tm_min=37, tm_sec=24, tm_wday=5, tm_yday=175, tm_isdst=0)
>>> now = time.localtime(time.time())
>>> print(now.tm_year)
2017

时间转化为时间戳

>>> time.mktime(time.localtime())
1498315333.0

格式化时间

>>> time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
'2017-06-24 22:47:36'
>>> time.strptime('2017-06-24','%Y-%m-%d')
time.struct_time(tm_year=2017, tm_mon=6, tm_mday=24, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=175, tm_isdst=-1)

datetime模块

显示时间

>>> import datetime
>>> print(datetime.date.today())
2017-06-24
>>> print(datetime.date.fromtimestamp(time.time()))
2017-06-24

时间转换

>>> print(datetime.datetime.now())
2017-06-24 22:54:31.145610
>>> print(datetime.datetime.now().timetuple())
time.struct_time(tm_year=2017, tm_mon=6, tm_mday=24, tm_hour=23, tm_min=23, tm_sec=30, tm_wday=5, tm_yday=175, tm_isdst=-1)
>>> print(datetime.datetime.now().replace())
2017-06-24 23:26:09.277628
>>> print(datetime.datetime.now().replace(1994,4,16))
1994-04-16 23:26:24.975626
>>> print(datetime.datetime.strptime('16/04/1994 10:20','%d/%m/%Y %H:%M'))
1994-04-16 10:20:00

时间加减

>>> print(datetime.datetime.now() + datetime.timedelta(days=-1))
2017-07-03 19:28:49.459909
>>> print(type(datetime.datetime.now() + datetime.timedelta(days=-1)))
<type 'datetime.datetime'>

参数定义有这些可选项,默认为0

def __new__(cls, days=0, seconds=0, microseconds=0, 
            miliseconds=0, minutes=0, hours=0, weeks=0);

sys模块

  • __name__ 对于主文件,__name__ == "__main__",对于导入的时候,__name__就是模块名
  • __doc__ python文件注释
  • __file__ 文件本身的路径
  • __package__ 对于单独文件,为None
  • __cache__ 文件缓存的内容,为python3独有,输出可以看到是pyc文件的路径。
  • __builtins__ 内置函数

描述文档

>>> def func():
...     """This is doc"""
...     pass
... 
>>> func.__doc__
'This is doc'

文件本身路径的用途

(env35) [root@why ~]# python /root/aa.py 
/root
['/root', '/root/env35/lib/python35.zip', '/root/env35/lib/python3.5', '/root/env35/lib/python3.5/plat-linux', '/root/env35/lib/python3.5/lib-dynload', '/opt/python-3.5.0/lib/python3.5', '/opt/python-3.5.0/lib/python3.5/plat-linux', '/root/env35/lib/python3.5/site-packages', '/root/bin']
(env35) [root@why ~]# python aa.py 

['/root', '/root/env35/lib/python35.zip', '/root/env35/lib/python3.5', '/root/env35/lib/python3.5/plat-linux', '/root/env35/lib/python3.5/lib-dynload', '/opt/python-3.5.0/lib/python3.5', '/opt/python-3.5.0/lib/python3.5/plat-linux', '/root/env35/lib/python3.5/site-packages', 'bin']

文件所在目录

>>> import re
>>> print(re.__package__)
None

传入脚本参数

sys.argv是传递进来的参数,和shell脚本参数一样。

[root@why ~]# cat test.py
import sys
print(sys.argv)
[root@why ~]# python test.py parameter1 parameter2
['test.py', 'parameter1', 'parameter2']

模块搜素目录

>>> import sys
>>> print(sys.path)
['', '/usr/lib64/python2.6/site-packages/MySQL_python-1.2.3c1-py2.6-linux-x86_64.egg', '/usr/lib/python2.6/site-packages/cloud_init-0.7.6-py2.6.egg', '/usr/lib/python2.6/site-packages/jsonpatch-1.13-py2.6.egg', '/usr/lib/python2.6/site-packages/requests-2.9.1-py2.6.egg', '/usr/lib/python2.6/site-packages/argparse-1.4.0-py2.6.egg', '/usr/lib/python2.6/site-packages/Jinja2-2.8-py2.6.egg', '/usr/lib/python2.6/site-packages/jsonpointer-1.10-py2.6.egg', '/usr/lib/python2.6/site-packages/six-1.10.0-py2.6.egg', '/usr/lib/python2.6/site-packages/AliyunUtil-0.0.1-py2.6.egg', '/usr/lib/python2.6/site-packages/pip-1.5.4-py2.6.egg', '/usr/lib64/python26.zip', '/usr/lib64/python2.6', '/usr/lib64/python2.6/plat-linux2', '/usr/lib64/python2.6/lib-tk', '/usr/lib64/python2.6/lib-old', '/usr/lib64/python2.6/lib-dynload', '/usr/lib64/python2.6/site-packages', '/usr/lib64/python2.6/site-packages/gtk-2.0', '/usr/lib/python2.6/site-packages', '/usr/lib/python2.6/site-packages/setuptools-0.6c11-py2.6.egg-info']

首位为'',代表当前目录

不过在pycharm中,pycharm会默认把项目目录也加入到模块的路径中,我就经历过pycharm中代码正常运行,而放到linux环境就因为这个问题报错

['F:\\MyPython\\testsyspath', 'F:\\MyPython', 'C:\\Windows\\system32\\python27.zip', 'C:\\Python27\\DLLs', 'C:\\Python27\\lib', 'C:\\Python27\\lib\\plat-win', 'C:\\Python27\\lib\\lib-tk', 'C:\\Python27', 'C:\\Python27\\lib\\site-packages']

添加库

>>> sys.path.append('/etc/nginx')
>>> print(sys.path)
['', '/usr/lib64/python2.6/site-packages/MySQL_python-1.2.3c1-py2.6-linux-x86_64.egg', '/usr/lib/python2.6/site-packages/cloud_init-0.7.6-py2.6.egg', '/usr/lib/python2.6/site-packages/jsonpatch-1.13-py2.6.egg', '/usr/lib/python2.6/site-packages/requests-2.9.1-py2.6.egg', '/usr/lib/python2.6/site-packages/argparse-1.4.0-py2.6.egg', '/usr/lib/python2.6/site-packages/Jinja2-2.8-py2.6.egg', '/usr/lib/python2.6/site-packages/jsonpointer-1.10-py2.6.egg', '/usr/lib/python2.6/site-packages/six-1.10.0-py2.6.egg', '/usr/lib/python2.6/site-packages/AliyunUtil-0.0.1-py2.6.egg', '/usr/lib/python2.6/site-packages/pip-1.5.4-py2.6.egg', '/usr/lib64/python26.zip', '/usr/lib64/python2.6', '/usr/lib64/python2.6/plat-linux2', '/usr/lib64/python2.6/lib-tk', '/usr/lib64/python2.6/lib-old', '/usr/lib64/python2.6/lib-dynload', '/usr/lib64/python2.6/site-packages', '/usr/lib64/python2.6/site-packages/gtk-2.0', '/usr/lib/python2.6/site-packages', '/usr/lib/python2.6/site-packages/setuptools-0.6c11-py2.6.egg-info', '/etc/nginx']

os模块

方法 描述
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd
os.curdir 返回当前目录: ('.')
os.pardir 获取当前目录的父目录字符串名:('..')
os.makedirs('dir1/dir2') 可生成多层递归目录
os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove() 删除一个文件
os.rename("oldname","new") 重命名文件/目录
os.stat('path/filename') 获取文件/目录信息
os.sep 操作系统特定的路径分隔符,win下为"\",Linux下为"/"
os.linesep 当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep 用于分割文件路径的字符串
os.name 字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command") 运行shell命令,直接显示
os.environ 获取系统环境变量
os.path.abspath(path) 返回path规范化的绝对路径
os.path.split(path) 将path分割成目录和文件名二元组返回
os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素
os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path) 如果path是绝对路径,返回True
os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间
os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间

pickle模块

pickle模块可以将列表,数组等转换成字符串,进而存储到文件,或者从文件中读取字典,列表的字符串,将其转化为列表或字典

字典转换为字符串

import pickle
accounts={'b':2}
f = open('account.db','wb')
f.write(pickle.dumps(accounts))
f.close()

字符串转换为字典

import pickle
f = open('account.db','rb')
account_dic = pickle.loads(f.read())
f.close()
print(account_dic['b'])

更简洁的直接操作文件

import pickle
accounts={'c':3}
with open('account.db','wb') as f:
    pickle.dump(accounts,f)

import pickle
with open('account.db','rb') as f:
account_dic = pickle.load(f)
    print(account_dic['c'])

json模块

首先json模块支持上述四种dump,dumps,load和loads。

有时候可能需要进行字节的传递,在可以通过bytes处理

f.write(bytes(json.dumps(accounts),encoding='utf-8'))

account_dic = json.loads(f.read().decode('utf-8'))

pickle支持所有格式,但是只能在python中使用,而json格式只能处理列表,字典,但是json格式可以用于和其他语言交互

在python中,单引号是字符串,双引号也是字符串,但是在其他语言中,双引号一定是字符串,而单引号却不一定是,但是json处理字符串的时候,字符串一定要用双引号,外边是单引号,三引号都行。

浏览器返回的都是字符串,http请求的响应也都是字符串,跨平台一般都是使用json

hashlib模块

提供SHA1,SHA224,SHA256,SHA384,SHA512,MD5算法

md5加密密码

import hashlib
hash = hashlib.md5()
hash.update(bytes('123456'))
print(hash.hexdigest())

以上代码适用于python2.7,对于python3使用一下代码

import hashlib
hash = hashlib.md5()
hash.update(bytes('123456',encoding='utf-8'))
print(hash.hexdigest())

执行结果

e10adc3949ba59abbe56e057f20f883e

md5不可反解,就是说无法通过加密后的结果反推加密前,但是可以通过撞库的方式来实现,就是通过频繁的通过明文进行md5加密,然后获取明文与密文的对应关系。

不过也提供了用于加密防止撞库的方式来获取对应关系的方式

传参进行md5加密

import hashlib
hash = hashlib.md5('why')
hash.update(bytes('123456'))
print(hash.hexdigest())

执行结果

80ae50b4a97d1aac94343c1e7669801f

用于加密的hmac

python也自带一个hmac模块用于加密

import hmac
h = hmac.new('why')
h.update(bytes('123456'))
print(h.hexdigest())

执行结果

002d1aaff2b485e22f2235b104282eea

xml模块

测试代码

[root@why ~]# cat test.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>

xml解析

[root@why ~]# cat test.py 
from xml.etree import ElementTree as ET
# create ElementTree object
root = ET.XML(open('test.xml','r').read())

print(root.tag)

for node in root:
    print(node,type(node))
    print(node.tag,node.attrib,node.find('rank').text)
[root@why ~]# python test.py 
data
(<Element country at 7f5bcbc60440>, <type 'instance'>)
('country', {'name': 'Liechtenstein'}, '2')
(<Element country at 7f5bcbc605f0>, <type 'instance'>)
('country', {'name': 'Singapore'}, '5')
(<Element country at 7f5bcbc60758>, <type 'instance'>)
('country', {'name': 'Panama'}, '69')

tag获取的<>中的tag,而attrib获取的<>中的等式,返回值为字典,text获取的是<>和<>之间的内容,find则是在其子节点进行查询。

修改xml文件内容

python3中的iter()

(env35) [root@why ~]# cat test.py 
from xml.etree import ElementTree as ET
tree = ET.parse("test.xml")

root = tree.getroot()
#for node in root.iter('year'):
for node in root.getiterator('year'):
    new_year = int(node.text) + 1
    node.text = str(new_year)

tree.write("test.xml")


(env35) [root@why ~]# python test.py 
(env35) [root@why ~]# cat test.xml 
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2024</year>
        <gdppc>141100</gdppc>
        <neighbor direction="E" name="Austria" />
        <neighbor direction="W" name="Switzerland" />
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2027</year>
        <gdppc>59900</gdppc>
        <neighbor direction="N" name="Malaysia" />
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2027</year>
        <gdppc>13600</gdppc>
        <neighbor direction="W" name="Costa Rica" />
        <neighbor direction="E" name="Colombia" />
    </country>

python2中的getiterator()

[root@why ~]# cat test.py 
from xml.etree import ElementTree as ET
tree = ET.parse("test.xml")

root = tree.getroot()
#for node in root.iter('year'):
for node in root.getiterator('year'):
    new_year = int(node.text) + 1
    node.text = str(new_year)

tree.write("test.xml")
[root@why ~]# python test.py 
[root@why ~]# cat test.xml 
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2025</year>
        <gdppc>141100</gdppc>
        <neighbor direction="E" name="Austria" />
        <neighbor direction="W" name="Switzerland" />
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2028</year>
        <gdppc>59900</gdppc>
        <neighbor direction="N" name="Malaysia" />
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2028</year>
        <gdppc>13600</gdppc>
        <neighbor direction="W" name="Costa Rica" />
        <neighbor direction="E" name="Colombia" />
    </country>
</data>

python3中的getiterator()

(env35) [root@why ~]# python test.py 
(env35) [root@why ~]# cat test.py 
from xml.etree import ElementTree as ET
tree = ET.parse("test.xml")

root = tree.getroot()
#for node in root.iter('year'):
for node in root.getiterator('year'):
    new_year = int(node.text) + 1
    node.text = str(new_year)

tree.write("test.xml")
(env35) [root@why ~]# cat test.xml 
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2026</year>
        <gdppc>141100</gdppc>
        <neighbor direction="E" name="Austria" />
        <neighbor direction="W" name="Switzerland" />
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2029</year>
        <gdppc>59900</gdppc>
        <neighbor direction="N" name="Malaysia" />
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2029</year>
        <gdppc>13600</gdppc>
        <neighbor direction="W" name="Costa Rica" />
        <neighbor direction="E" name="Colombia" />
    </country>
</data>(env35)

xml添加内容

(env35) [root@why ~]# cat test.py 
from xml.etree import ElementTree as ET
tree = ET.parse("test.xml")

root = tree.getroot()
for node in root.iter('year'):
#for node in root.getiterator('year'):
#    new_year = int(node.text) + 1
#    node.text = str(new_year)
     node.set('name','why')   
tree.write("test.xml")
(env35) [root@why ~]# python test.py 
(env35) [root@why ~]# cat test.xml 
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year name="why">2026</year>
        <gdppc>141100</gdppc>
        <neighbor direction="E" name="Austria" />
        <neighbor direction="W" name="Switzerland" />
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year name="why">2029</year>
        <gdppc>59900</gdppc>
        <neighbor direction="N" name="Malaysia" />
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year name="why">2029</year>
        <gdppc>13600</gdppc>
        <neighbor direction="W" name="Costa Rica" />
        <neighbor direction="E" name="Colombia" />
    </country>

xml其他方法

print(dir(root))
['__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']

random

生成验证码

import random
temp = ''
for i in range(6):
    num = random.randrange(0,4)
    if num >= 2:
        rad2 = random.randrange(0,10)
        temp = temp + str(rad2)
    else:
        rad1 = random.randrange(65,91)
        c1 = chr(rad1)
        temp = temp + c1
print(temp)

生成随机id

def get_id(cls, title="rid", length=8):
    """
        生成固定长度随机字符串。
    :param title:
        字符串头
    :param length:
        字符串长度。
    :return:
        string
    """
    str = "abcdefghijklmnopqrstuvwxyz0123456789"
    return title + '-' + ''.join(random.sample(str, length))

configparser

configparser是一个读写固定格式的配置文件的方法

首先要注意的是配置文件中获取出来的都是字符串格式

(env35) [root@why ~]# cat test.ini 
# 注释
; 注释

[why]      #节点
name = wanghongyu
age : 23
[pqt]   #节点
name = panqiutong

获取所有节点

(env35) [root@why ~]# cat testconf.py 
# -*- coding:utf-8 -*-
import configparser

con = configparser.ConfigParser()
con.read("test.ini")
a = []
result = con.sections()
print(result)

(env35) [root@why ~]# python testconf.py 
['why', 'pqt']

获取所有key

(env35) [root@why ~]# vi testconf.py 
# -*- coding:utf-8 -*-
import configparser

con = configparser.ConfigParser()
con.read("test.ini")
a = []

ret = con.options("why")
print(ret)

执行结果

(env35) [root@why ~]# python testconf.py 
['name', 'age']

获取所有键值对

ret = con.items("why")
print(ret)

执行结果

[('name', 'wanghongyu'), ('age', '23')]

获取指定配置

ret = con.get("why","age")
print(ret,type(ret))

执行结果

23 <class 'str'>

监测section是否存在

ret = con.has_section("why")
print(ret)

执行结果

True

添加section

con.add_section("mb")
con.write(open("test.ini","w"))

(env35) [root@why ~]# python testconf.py 
(env35) [root@why ~]# cat test.ini 
[why]
name = wanghongyu
age = 23

[pqt]
name = panqiutong

[mb]

可以看到注释已经没有

删除section

con.remove_section("mb")
con.write(open("test.ini","w"))

对内部配置处理的

config.has_option('section', 'k1')      #检查
remove_option('section', 'k1')          #删除
set('section', 'k10', "123")            #设置

requests模块

logging模块

import  logging

logging.basicConfig(filename='test.log',
                    format='%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S %p',
                    level=10,
                    )

logging.error("This is test error!")

执行结果

2017-07-05 19:04:51 PM - root - ERROR - testlogging: This is test error!

logging.basicConfig函数各参数:

  • filename: 指定日志文件名
  • filemode: 和file函数意义相同,指定日志文件的打开模式,'w'或'a'
  • format: 指定输出的格式和内容
  • datefmt: 指定时间格式,同time.strftime()
  • level: 设置日志级别,默认为logging.WARNING
  • stream: 指定将日志的输出流,可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,当stream和filename同时指定时,stream被忽略

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: 打印日志信息

各个级别代表的值

  • CRITICAL = 50
  • FATAL = CRITICAL
  • ERROR = 40
  • WARNING = 30
  • WARN = WARNING
  • INFO = 20
  • DEBUG = 10
  • NOTSET = 0

shutil

拷贝文件内容

import shutil

shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))

拷贝文件

shutil.copyfile('f1.log', 'f2.log')

拷贝文件的内容,组,用户不变

shutil.copymode('f1.log', 'f2.log')

拷贝权限

shutil.copystat('f1.log', 'f2.log')

拷贝文件和权限

shutil.copy(src, dst)

递归拷贝文件夹

shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))

ignore=shutil.ignore_patterns('*.pyc', 'tmp*')代表忽略*.pyctmp*文件

递归删除文件夹

shutil.rmtree('folder1')

递归移动文件或文件夹(等效linux的mv)

shutil.move('folder1', 'folder3')

创建压缩包

import shutil
ret = shutil.make_archive("/home/why/whytest", 'gztar', root_dir='/home/why/test')

base_name,format,root_dir,还有owner,group和logger

format是压缩的种类,有zip,tar,bztar和gztar

实质调用的是

import zipfile

# 压缩
z = zipfile.ZipFile('why.zip', 'w')
z.write('a.log')
z.write('data.data')
z.close()

# 解压
z = zipfile.ZipFile('why.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()

zipfile还有namelist显示压缩包内容,extract解压出来单独文件的操作

paramiko

paramiko是一个远程控制模块,fabric和ansible内部就是通过paramiko来实现的

连接远程执行命令

#!/usr/bin/env python
#coding:utf-8

import paramiko

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.1.108', 22, 'why', '123')
stdin, stdout, stderr = ssh.exec_command('df')
print stdout.read()
ssh.close();

通过私钥方式

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('主机名 ', 端口, '用户名', key)

stdin, stdout, stderr = ssh.exec_command('df')
print stdout.read()
ssh.close()

上传下载文件

上传

import os,sys
import paramiko

t = paramiko.Transport(('182.92.219.86',22))
t.connect(username='wupeiqi',password='123')
sftp = paramiko.SFTPClient.from_transport(t)
sftp.put('/tmp/test.py','/tmp/test.py') 
t.close()

下载

import os,sys
import paramiko

t = paramiko.Transport(('182.92.219.86',22))
t.connect(username='wupeiqi',password='123')
sftp = paramiko.SFTPClient.from_transport(t)
sftp.get('/tmp/test.py','/tmp/test2.py')
t.close()

通过私钥方式上传和下载文件

上传

import paramiko

pravie_key_path = '/home/auto/.ssh/id_rsa'
key = paramiko.RSAKey.from_private_key_file(pravie_key_path)

t = paramiko.Transport(('182.92.219.86',22))
t.connect(username='wupeiqi',pkey=key)

sftp = paramiko.SFTPClient.from_transport(t)
sftp.put('/tmp/test3.py','/tmp/test3.py') 

t.close()

下载

import paramiko

pravie_key_path = '/home/auto/.ssh/id_rsa'
key = paramiko.RSAKey.from_private_key_file(pravie_key_path)

t = paramiko.Transport(('182.92.219.86',22))
t.connect(username='wupeiqi',pkey=key)

sftp = paramiko.SFTPClient.from_transport(t)
sftp.get('/tmp/test3.py','/tmp/test4.py') 

t.close()

未完待续