Python全栈开发之5、模块

一、模块

1、import导入模块

#1.定义
模块:用来从逻辑上组织python代码(变量,函数,类,逻辑),本质就是.py结尾的python文件,实现一个功能
包:python package 用来从逻辑上组织模块  本质就是一个目录(必须带有一个__init__.py的文件)

#2.导入方法
import module
import module1,module2   导入多个模块
from module import *     导入所有  不推荐慎用(可能会覆盖本文件中自定义的同名函数)
from module  import  logger as logger_sunhao   创建别名
from module import m1,m2,m3

#3.import模块本质(路径搜索和搜索路径)
import sys
print(sys.path)  sys.path路径就是当前执行文件所在的路径
import module ---> module.py ----> module.py的路径 ---> sys.path

#4.导入优化
from module_test import test

#5.模块的分类
  1.标准库
    time与datetime
  2.开源模块
  3.自定义模块

 

 #1、bin执行文件的路径是'E:\Python学习2019',如果想调用web3目录下的main.py模块,需要  from web1.web2.web3 import main  这样调用

#2、main.py和cal.py虽然都在web3目录下,但是如果main.py想调用cal.py必须这样写:from web1.web2.web3 import cal  因为执行文件的路径只有一个就是:'E:\Python学习2019'

#3、bin和module目录是同级目录,如果想在bin.py中直接from module import main调用module目录中的文件,需要把路径加到环境变量中。
BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)

二、动态导入模块 importlib.import_module

 

三、time和datetime时间模块

1、time

在Python中,通常有这几种方式来表示时间:

1、时间戳
2、格式化的时间字符串
3、元组(struct_time)共九个元素。

由于Python的time模块实现主要调用C库,所以各个平台可能有所不同。

UTC(Coordinated Universal Time,世界协调时)亦即格林威治天文时间,世界标准时间。在中国为UTC+8。DST(Daylight Saving Time)即夏令时。

时间戳(timestamp)的方式:通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。返回时间戳方式的函数主要有time(),clock()等。

元组(struct_time)方式:struct_time元组共有9个元素,返回struct_time的函数主要有gmtime(),localtime(),strptime()。下面列出这种方式元组中的几个元素:
 1 # -*-coding:utf-8-*-
 2 import time
 3 print(time.time())      #获取一个时间戳 从1970年开始按秒计时的一个浮点型数值
 4 print(time.localtime()) #返回一个struct_time元组类型序列 里面元素包含年,月,日等九个元素
 5 print(time.timezone)    #返回一个值 单位为秒 
 6 print(time.asctime())   #返回当前时间字符串格式
 7 time.sleep(2) #睡眠几秒
 8 
 9 time.gmtime()  #把时间戳转换成元组,但是时间是UTC时间
10 time.gmtime(time.time()-time.timezone)  #把UTC时间转换成当地时间
11 print(time.localtime())  #把时间戳转换成元组,但是时间是当地时间  结果为UTC+8时区
x=time.localtime()
print(x.tm_year)  #获取年
print(x.tm_mon)  #获取月
print(x.tm_mday) #获取日
print(x.tm_hour)  #获取时
print(x.tm_min)  #获取分
print(time.mktime(x)) #元组转换成时间戳

#元组转换成格式化字符串时间
time.strftime("%Y-%m-%d  %H:%M:%S",time.localtime())  

#把格式化字符串转换成元组
time.strptime('2017-10-17','%Y-%m-%d')  
%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    时区的名字(如果不存在为空字符)    
%%    ‘%’字符

2、datetime时间模块

import datetime
 
# print(datetime.datetime.now()) #返回 2016-08-19 12:47:03.941925
#print(datetime.date.fromtimestamp(time.time()) )  # 时间戳直接转成日期格式 2016-08-19
# print(datetime.datetime.now() )
# print(datetime.datetime.now() + datetime.timedelta(3)) #当前时间+3天
# print(datetime.datetime.now() + datetime.timedelta(-3)) #当前时间-3天
# print(datetime.datetime.now() + datetime.timedelta(hours=3)) #当前时间+3小时
# print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #当前时间+30分
# c_time  = datetime.datetime.now()
# print(c_time.replace(minute=3,hour=2)) #时间替换

 四、 re模块(正则表达式)

'.'     默认匹配除
之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行
'^'     匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","
abc
eee",flags=re.MULTILINE)
'$'     匹配字符结尾,或e.search("foo$","bfoo
sdfsf",flags=re.MULTILINE).group()也可以
'*'     匹配*号前的字符0次或多次,re.findall("ab*","cabb3abcbbac")  结果为['abb', 'ab', 'a']
'+'     匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb']
'?'     匹配前一个字符1次或0次
'{m}'   匹配前一个字符m次
'{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb']
'|'     匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果'ABC'
'(...)' 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c
 
 
'A'    只从字符开头匹配,re.search("Aabc","alexabc") 是匹配不到的
''    匹配字符结尾,同$
'd'    匹配数字0-9
'D'    匹配非数字
'w'    匹配[A-Za-z0-9]
'W'    匹配非[A-Za-z0-9]
's'     匹配空白字符、	、
、
 , re.search("s+","ab	c1
3").group() 结果 '	'
 
'(?P<name>...)' 分组匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city") 结果{'province': '3714', 'city': '81', 'birthday': '1993'} 
常用正则表达式符号
re.match   # 只从开头开始匹配 
re.search  # 从整个文本匹配 返回一个对象  这个对象调用group()方法 查看 
re.findall    # 把所有匹配到的字符放到以列表中的元素返回    #返回所有满足匹配条件的结果,放在列表里
re.splitall   # 以匹配到的字符当做列表分隔符
re.sub       # 匹配字符并替换  ret = re.sub('a..a','skmb','hasascascasda') print(ret)

re.splite
obj = re.compile('.com')    #编译方法  先把要匹配的字符串编译成一个对象  
ret = obj.findall('asdasd.comasdas')
print(ret)
用法

 五、random随机模块

import random
print (random.random())  #0.6445010863311293  
#random.random()用于生成一个0到1的随机符点数: 0 <= n < 1.0

print (random.randint(1,7)) #4 #random.randint()的函数原型为:random.randint(a, b),用于生成一个指定范围内的整数。 # 其中参数a是下限,参数b是上限,生成的随机数n: a <= n <= b

print (random.randrange(1,10)) #5 #random.randrange的函数原型为:random.randrange([start], stop[, step]), # 从指定范围内,按指定基数递增的集合中 获取一个随机数。如:random.randrange(10, 100, 2), # 结果相当于从[10, 12, 14, 16, ... 96, 98]序列中获取一个随机数。 # random.randrange(10, 100, 2)在结果上与 random.choice(range(10, 100, 2) 等效。
print(random.choice('liukuni')) #i

#random.choice从序列中获取一个随机元素。 # 其函数原型为:random.choice(sequence)。参数sequence表示一个有序类型。 # 这里要说明一下:sequence在python不是一种特定的类型,而是泛指一系列的类型。 # list, tuple, 字符串都属于sequence。有关sequence可以查看python手册数据模型这一章。 # 下面是使用choice的一些例子: print(random.choice("学习Python"))# print(random.choice(["JGood","is","a","handsome","boy"])) #List print(random.choice(("Tuple","List","Dict"))) #List

print(random.sample([1,2,3,4,5],3)) #[1, 2, 5] #random.sample的函数原型为:random.sample(sequence, k),从指定序列中随机获取指定长度的片断。sample函数不会修改原有序列。
import random
import string
#随机整数:
print( random.randint(0,99))  #70
 
#随机选取0到100间的偶数:
print(random.randrange(0, 101, 2)) #4
 
#随机浮点数:
print( random.random()) #0.2746445568079129
print(random.uniform(1, 10)) #9.887001463194844
 
#随机字符:
print(random.choice('abcdefg&#%^*f')) #f
 
#多个字符中选取特定数量的字符:
print(random.sample('abcdefghij',3)) #['f', 'h', 'd']
 
#随机选取字符串:
print( random.choice ( ['apple', 'pear', 'peach', 'orange', 'lemon'] )) #apple

#洗牌# items = [1,2,3,4,5,6,7] print(items) #[1, 2, 3, 4, 5, 6, 7] random.shuffle(items) print(items) #[1, 4, 7, 2, 5, 3, 6]
import random

check_code=''

for i in range(5):
    current=random.randrange(0,5)
    if current==i:
        tmp=chr(random.randrange(65,90))
    else:
        tmp=random.randint(0,9)

    check_code+=str(tmp)

print(check_code)
随机获取验证码示例

 六、OS模块

import os
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname")  改变当前脚本工作目录;相当于shell下cd
os.curdir  返回当前目录: ('.')
os.pardir  获取当前目录的父目录字符串名:('..')
os.makedirs('dirname1/dirname2')    可生成多层递归目录
os.removedirs('dirname1')    若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname')    生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname')    删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname')    列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove()  删除一个文件
os.rename("oldname","newname")  重命名文件/目录
os.stat('path/filename')  获取文件/目录信息
os.sep    输出操作系统特定的路径分隔符,win下为"\",Linux下为"/"
os.linesep    输出当前平台使用的行终止符,win下为"	
",Linux下为"
"
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所指向的文件或者目录的最后修改时间

七、sys模块

sys.argv           命令行参数List,第一个元素是程序本身路径
sys.exit(n)        退出程序,正常退出时exit(0)
sys.version        获取Python解释程序的版本信息
sys.maxint         最大的Int值
sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform       返回操作系统平台名称
sys.stdin          输入相关
sys.stdout         输出相关
sys.stderror       错误相关

 八、json&pickle序列化模块

1、json

用于序列化的两个模块

  • json   用于字符串和python数据类型间进行转换,json只支持列表,字典这样简单的数据类型 但是它不支持类,函数这样的数据类型转换
  • pickle  它支持所有数据类型 这就是pickle和json的区别,它可以对复杂数据类型做操作,缺点是仅适用于python

Json模块提供了四个功能:dumps、dump、loads、load

import json

#dumps和loads只是在内存中转换

dic={'k1':'v1'}

dic1=json.dumps(dic) #将python的基本数据类型转换成字符串形式
print(type(dic))
print(type(dic1))


s1='{"k2":"v2"}'
dic2=json.loads(s1)  #将python的字符串形式转换成基本数据类型

print(type(s1))
print(type(dic2))
dumps(dict)和loads(str)
import json

'''json.dump()    具有写文件和读文件的功能
  json.load()
'''
li=[11,22,33]
json.dump(li,open('db','w'))

ret=json.load(open('db','r'))
print(ret[0])
print(ret,type(ret))
dump()和load()

 2、pickle

 pickle模块提供了四个功能:dumps、dump、loads、load

import pickle

li=[11,22,33]

ret=pickle.dumps(li)

print(ret)  #打印出来的结果是字节码b'x80x03]qx00(Kx0bKx16K!e.'

result=pickle.loads(ret)
print(result)


#pickle支持类,函数这样复杂数据类型的操作
class foo():
    def __init__(self):
        pass

f=foo()
ret2=pickle.dumps(f)
print(ret2)

ret3=pickle.loads(ret2)
print(ret3)
dumps&loads
import pickle

li=[11,22,33]

pickle.dump(li,open('db1','wb'))  #写入文件

ret1=pickle.load(open('db1','rb'))

print(ret1)
dump()&load()

 3、软件目录结构规范

设计好目录结构用途:

可读性高: 不熟悉这个项目的代码的人,一眼就能看懂目录结构,知道程序启动脚本是哪个,测试目录在哪儿,配置文件在哪儿等等。从而非常快速的了解这个项目。
可维护性高: 定义好组织规则后,维护者就能很明确地知道,新增的哪个文件和代码应该放在什么目录之下。这个好处是,随着时间的推移,代码 / 配置的规模增加,项目结构不会混乱,仍然能够组织良好。


目录组织方式

关于如何组织一个较好的Python工程目录结构,已经有一些得到了共识的目录结构。在Stackoverflow的这个问题上,能看到大家对Python目录结构的讨论。

Foo /
| -- bin /
| | -- foo
|
| -- foo /
| | -- tests /
| | | -- __init__.py
| | | -- test_main.py
| |
| | -- __init__.py
| | -- main.py
|
| -- docs /
| | -- conf.py
| | -- abc.rst
|
| -- setup.py
| -- requirements.txt
| -- README

简要解释一下:

bin /: 存放项目的一些可执行文件,当然你可以起名script / 之类的也行。
foo /: 存放项目的所有源代码。(1)
源代码中的所有模块、包都应该放在此目录。不要置于顶层目录。(2)
其子目录tests / 存放单元测试代码; (3)
程序的入口最好命名为main.py。
docs /: 存放一些文档。
setup.py: 安装、部署、打包的脚本。
requirements.txt: 存放软件依赖的外部Python包列表。
README: 项目说明文件。


除此之外,有一些方案给出了更加多的内容。比如LICENSE.txt, ChangeLog.txt文件等,我没有列在这里,因为这些东西主要是项目开源的时候需要用到。如果你想写一个开源软件,目录该如何组织,可以参考这篇文章。

下面,再简单讲一下我对这些目录的理解和个人要求吧。

关于README的内容
这个我觉得是每个项目都应该有的一个文件,目的是能简要描述该项目的信息,让读者快速了解这个项目。

它需要说明以下几个事项:

软件定位,软件的基本功能。
运行代码的方法: 安装环境、启动命令等。
简要的使用说明。
代码目录结构说明,更详细点可以说明软件的基本原理。
常见问题说明。
我觉得有以上几点是比较好的一个README。在软件开发初期,由于开发过程中以上内容可能不明确或者发生变化,并不是一定要在一开始就将所有信息都补全。但是在项目完结的时候,是需要撰写这样的一个文档的。

可以参考Redis源码中Readme的写法,这里面简洁但是清晰的描述了Redis功能和源码结构。



关于requirements.txt和setup.py
setup.py
一般来说,用setup.py来管理代码的打包、安装、部署问题。业界标准的写法是用Python流行的打包工具setuptools来管理这些事情。这种方式普遍应用于开源项目中。不过这里的核心思想不是用标准化的工具来解决这些问题,而是说,一个项目一定要有一个安装部署工具,能快速便捷的在一台新机器上将环境装好、代码部署好和将程序运行起来。

这个我是踩过坑的。

我刚开始接触Python写项目的时候,安装环境、部署代码、运行程序这个过程全是手动完成,遇到过以下问题:

安装环境时经常忘了最近又添加了一个新的Python包,结果一到线上运行,程序就出错了。
Python包的版本依赖问题,有时候我们程序中使用的是一个版本的Python包,但是官方的已经是最新的包了,通过手动安装就可能装错了。
如果依赖的包很多的话,一个一个安装这些依赖是很费时的事情。
新同学开始写项目的时候,将程序跑起来非常麻烦,因为可能经常忘了要怎么安装各种依赖。
setup.py可以将这些事情自动化起来,提高效率、减少出错的概率。"复杂的东西自动化,能自动化的东西一定要自动化。"
是一个非常好的习惯。

setuptools的文档比较庞大,刚接触的话,可能不太好找到切入点。学习技术的方式就是看他人是怎么用的,可以参考一下Python的一个Web框架,flask是如何写的: setup.py

当然,简单点自己写个安装脚本(deploy.sh)替代setup.py也未尝不可。

requirements.txt
这个文件存在的目的是:

方便开发者维护软件的包依赖。将开发过程中新增的包添加进这个列表中,避免在setup.py安装依赖时漏掉软件包。
方便读者明确项目使用了哪些Python包。
这个文件的格式是每一行包含一个包依赖的说明,通常是flask >= 0.10
这种格式,要求是这个格式能被pip识别,这样就可以简单的通过
pip
install - r
requirements.txt来把所有Python包依赖都装好了。具体格式说明: 点这里。



关于配置文件的使用方法
注意,在上面的目录结构中,没有将conf.py放在源码目录下,而是放在docs / 目录下。
很多项目对配置文件的使用做法是:

配置文件写在一个或多个python文件中,比如此处的conf.py。
项目中哪个模块用到这个配置文件就直接通过import
conf这种形式来在代码中使用配置。
这种做法我不太赞同:

这让单元测试变得困难(因为模块内部依赖了外部配置)
另一方面配置文件作为用户控制程序的接口,应当可以由用户自由指定该文件的路径。
程序组件可复用性太差,因为这种贯穿所有模块的代码硬编码方式,使得大部分模块都依赖conf.py这个文件。
所以,我认为配置的使用,更好的方式是,

模块的配置都是可以灵活配置的,不受外部配置文件的影响。
程序的配置也是可以灵活控制的。
能够佐证这个思想的是,用过nginx和mysql的同学都知道,nginx、mysql这些程序都可以自由的指定用户配置。

所以,不应当在代码中直接import
conf来使用配置文件。上面目录结构中的conf.py,是给出的一个配置样例,不是在写死在程序中直接引用的配置文件。可以通过给main.py启动参数指定配置路径的方式来让程序读取配置内容。当然,这里的conf.py你可以换个类似的名字,比如settings.py。或者你也可以使用其他格式的内容来编写配置文件,比如settings.yaml之类的。
软件目录结构规范

九、logging模块

 1、默认日志级别和简单应用

import logging

# 默认日志级别
NOTSET = 0 #不设置
DEBUG = 10
INFO = 20
WARNING = 30 #WARN = WARNING
ERROR = 40
CRITICAL = 50 #FATAL = CRITICAL


#调整日志基础设定
logging.basicConfig(
    level=logging.DEBUG,    # 调整日志级别
    filename='logging.log', # 日志文件
    filemode='w',           # 不追加日志格式,默认为a追加模式
    format="%(asctime)s [%(lineno)d]%(filename)s%(message)s%(threadName)s%(thread)s"  # 日志输出格式
)


logging.debug('调试debug message')
logging.info('消息info message')
logging.warning('警告warn message')
logging.error('错误error message')
logging.critical('严重critical message')
logging.basicConfig(
    level=logging.DEBUG,    # 调整日志级别
    filename='logging.log', # 日志文件
    filemode='w',           # 不追加日志格式,默认为a追加模式
    format="%(asctime)s [%(lineno)d]%(filename)s%(message)s%(threadName)s%(thread)s"  # 日志输出格式
)

#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:用户输出的消息
logging.basicConfig()设置日志全局配置

 2、logger对象

#-*-coding:utf-8-*-

import logging


def logger(file_name):

    logger=logging.getLogger()

    logger.setLevel("DEBUG")  # 设置日志级别
    fm=logging.Formatter("%(asctime)s [%(lineno)d]%(filename)s%(message)s%(threadName)s%(thread)s")  #设置日志格式


    file_log=logging.FileHandler(file_name) # 创建日志写文件对象
    stream_log=logging.StreamHandler()       # 创建日志打印屏幕对象


    file_log.setFormatter(fm)  # 设置对象日志格式
    stream_log.setFormatter(fm) # 设置对象日志格式


    logger.addHandler(file_log)
    logger.addHandler(stream_log)

    return logger

logger=logger("test.log")

logger.debug('调试debug message')
logger.info('消息info message')
logger.warning('警告warn message')
logger.error('错误error message')
logger.critical('严重critical message')

 十、configparser模块

configparser用于处理特定格式的文件,其本质上是利用open来操作文件。

#指定格式

#注释
;注释2

[nick]           #节点
age = 18         #
gender = ning    #
dearm = girl     #

[jenny]          #节点
age = 21         #
gender = jia     #

1、获取所有节点

import configparser
 
con = configparser.ConfigParser()
con.read("ini",encoding="utf-8")
 
result = con.sections()
print(result)

2、获取指定节点下所有的键值对

import configparser
 
con = configparser.ConfigParser()
con.read("ini",encoding="utf-8")
 
result = con.items("nick")
print(result)

3、获取指定节点下所有的键

import configparser
 
con = configparser.ConfigParser()
con.read("ini",encoding="utf-8")
 
ret = con.options("nick")
print(ret)

4、获取指定节点下指定key的值

import configparser
 
con = configparser.ConfigParser()
con.read("ini",encoding="utf-8")
 
v = con.get("nick","age")
v = con.get("nick","gender")
v = con.get("jenny","age")
v = con.get("jenny","gender")
print(v)

5、检查、删除、添加节点

#检查、删除、添加节点
import configparser
 
con = configparser.ConfigParser()
con.read("ini",encoding="utf-8")
 
#检查
has_sec = con.has_section("nick")
print(has_sec)
 
#添加节点
con.add_section("car")
con.write(open("ini","w"))
 
#删除节点
con.remove_section("car")
con.write(open("ini","w"))

6、检查、删除、设置指定组内的键值对

#检查、删除、设置指定组内的键值对
import configparser
 
con = configparser.ConfigParser()
con.read("ini",encoding="utf-8")
 
#检查
hac_opt = con.has_option("nick","age")
print(hac_opt)
 
#删除
con.remove_option("nick","dearm")
con.write(open("ini","w"))
 
#设置
con.set("nick","dearm","girl")
con.write(open("ini","w"))

 shutil模块

高级的 文件、文件夹、压缩包 处理模块

#将文件内容拷贝到另一个文件中
shutil.copyfileobj(fsrc,fdst,length)  
f1=open('old.xml','r')
f2=open('new.xml','w')

shutil.copyfileobj(f1,f2)
shutil.copyfile(src,dst)  #拷贝文件

shutil.copyfile('f1_old.log','f2_new.log')
shutil.copymode(src, dst)  #仅拷贝权限。内容、组、用户均不变
shutil.copymode('f1.log', 'f2.log')
shutil.copystat(src, dst)  #仅拷贝状态的信息,包括:mode bits, atime, mtime, flags  src,dst文件都必须存在

shutil.copystat('f1.log', 'f2.log')
shutil.copy(src, dst)  #拷贝文件和权限
shutil.copy('f1.log', 'f2.log')
shutil.copy2(src, dst) #拷贝文件和状态信息
shutil.copytree(src, dst, symlinks=False, ignore=None) #递归的去拷贝文件夹

shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))
shutil.rmtree(path[, ignore_errors[, onerror]]) #递归的去删除文件
shutil.rmtree('folder1')
shutil.move(src, dst)  #递归的去移动文件,它类似mv命令,其实就是重命名。
shutil.make_archive(base_name, format,...)

# 创建压缩包并返回文件路径,例如:zip、tar

# 创建压缩包并返回文件路径,例如:zip、tar

# base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
# 如:www                        =>保存至当前路径
# 如:/Users/wupeiqi/www =>保存至/Users/wupeiqi/
# format:    压缩包种类,“zip”, “tar”, “bztar”,“gztar”
# root_dir:    要压缩的文件夹路径(默认当前目录)
# owner:    用户,默认当前用户
# group:    组,默认当前组
# logger:    用于记录日志,通常是logging.Logger对象
#将 /Users/wupeiqi/Downloads/test 下的文件打包放置当前程序目录

import shutil ret = shutil.make_archive("wwwwwwwwww", 'gztar', root_dir='/Users/wupeiqi/Downloads/test') #将 /Users/wupeiqi/Downloads/test 下的文件打包放置 /Users/wupeiqi/目录 import shutil ret = shutil.make_archive("/Users/wupeiqi/wwwwwwwwww", 'gztar', root_dir='/Users/wupeiqi/Downloads/test')

 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()

zipfile解压缩


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()

tarfile解压缩

hashlib模块

 用于加密相关的操作,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

import hashlib,hmac

m1=hashlib.md5()

m1.update(b"hello")

print(m1.hexdigest())
m1.update(b"it is me")  #更新 第二次update是与第一次update拼接起来

print(m1.hexdigest())

m2=hashlib.md5()

m2.update(b"helloit is me")
print(m2.hexdigest())

s1=hashlib.sha1()
s1.update(b"hello")
print(s1.hexdigest())
s1.update(b"it is me")
print(s1.hexdigest())

s2=hashlib.sha1()
s2.update(b"helloit is me")
print(s2.hexdigest())


m3=hashlib.md5()

m3.update("天王盖地虎".encode(encoding="utf-8"))

print(m3.hexdigest())



h=hmac.new("你是二百五".encode(encoding='utf-8'))

print(h.hexdigest())

paramiko模块

该模块基于SSH用于连接远程服务器并执行相关操作

SSHClient

用于连接远程服务器并执行基本命令

基于用户名密码连接:

# -*-coding:utf-8-*-
# Author:sunhao

import paramiko

ssh= paramiko.SSHClient()   #创建ssh对象

# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())


#连接服务器
ssh.connect(hostname='192.168.10.141',port=22,username='root',password='123456')


#执行命令

stdin,stdout,stderr=ssh.exec_command("ps aux  ")

#获取命令结果
result=stdout.read()

print(result.decode())


#关闭链接
ssh.close()

基于ssh秘钥连接 

# -*-coding:utf-8-*-
# Author:sunhao

import  paramiko

private_key = paramiko.RSAKey.from_private_key_file('id_rsa')    #这是192.168.10.141上的私钥



ssh = paramiko.SSHClient()

ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

ssh.connect(hostname='192.168.10.180',port=22,username='root',pkey=private_key)  #192.168.10.141上的公钥在10.180上放着


stdin,stdout,stderr=ssh.exec_command("netstat -lpn;df -h;ps aux |grep ssh")

#获取命令结果

result=stdout.read()

print(result.decode())


#关闭链接
ssh.close()

SFTPClient

用于连接远程服务器并执行上传下载

# -*-coding:utf-8-*-
# Author:sunhao

import paramiko

transport=paramiko.Transport('192.168.10.141',22)     #远程服务器为192.168.10.141

transport.connect(username='root',password='123456')

sftp = paramiko.SFTPClient.from_transport(transport)

# 将本地paramiko模块-ssh.py 上传至服务器 /tmp/paramiko模块

#sftp.put('paramiko模块-ssh.py', '/home/paramiko模块')

# 将服务器/tmp/zabbix_server.log 下载到本地

sftp.get('/tmp/zabbix_server.log', 'zabbix_server.log')

transport.close()
原文地址:https://www.cnblogs.com/sunhao96/p/7698843.html