py4经常使用模块

导入模块方式

import 单文件
from dir import file 目录下文件
若是有相同的名称,能够采用别名的方式
from dir import file as rename.file

pip3 requests install
源码下载后会出现STEUP.PY文件,而后PYTHON STEUP.PY INSTALL
注意依赖关系

__name__是什么鬼html

# !/usr/bin/env python
# _*_coding:utf-8_*_
# Author:Joker


"""
my 注释
"""

# print(__doc__) # 获取文件注释

# print(__cached__)  # 字节码路径 pyc

# print(__file__) # 当前运行的py的路径,若是你跳到路径执行,就只显示文件名

import os
print(os.path.abspath(__file__)) # 永远的绝对路径

print(os.path.dirname(os.path.abspath(__file__)))  # 上一级目录

import sys
sys.path.append(os.path.dirname(os.path.abspath(__file__))) # 上级目录添加到变量

import s2
print(s2.__package__) # 包位置
# /Users/liqianlong/Desktop/Django project/kkk/s6-python-develop/day21-模块&包&--file--&开发规范

print(__name__) # __main__  执行当前文件时,当前文件的特殊变量__name__ == '__main__'  

模块学习

#!/usr/bin/env python
#_*_coding:utf-8_*_

# os模块
# os模块是与操做系统交互的一个接口
'''
os.walk() 显示目录下全部文件和子目录以元祖的形式返回,第一个是目录,第二个是文件夹,第三个是文件
open(r'tmp\inner\file',w)    建立文件
os.getcwd() 获取当前工做目录,即当前python脚本工做的目录路径  能够先记录当前文件目录
os.chdir("dirname")  改变当前脚本工做目录;至关于shell下cd
os.curdir  返回当前目录: ('.')   没什么用
os.pardir  获取当前目录的父目录字符串名:('..')    没什么用
os.makedirs('dirname1/dirname2')    可生成多层递归目录 dirname1若是存在就在下面建立,不存在都建立,若是都存在就报错,可经过
                                    修改里面exist_ok=ok来解决这个报错
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下为"\t\n",Linux下为"\n"
os.pathsep    输出用于分割文件路径的字符串 win下为;,Linux下为:
os.name    输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command")  运行shell命令,直接显示
os.popen("bash command)  运行shell命令,获取执行结果
print(ret.read())   这样读取出来popen的结果
os.environ  获取系统环境变量

os.path 括号内pathn就是文件夹和文件
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[, ...]])  将多个路径组合后返回,第一个绝对路径以前的参数将被忽略
print(os.path.join(os.getcwd(),'filename'))
os.path.getatime(path)  返回path所指向的文件或者目录的最后访问时间
os.path.getmtime(path)  返回path所指向的文件或者目录的最后修改时间
os.path.getsize(path) 返回path的大小
'''
# 注意:os.stat('path/filename')  获取文件/目录信息 的结构说明
'''
stat 结构:
st_mode: inode 保护模式
st_ino: inode 节点号。
st_dev: inode 驻留的设备。
st_nlink: inode 的连接数。
st_uid: 全部者的用户ID。
st_gid: 全部者的组ID。
st_size: 普通文件以字节为单位的大小;包含等待某些特殊文件的数据。
st_atime: 上次访问的时间。
st_mtime: 最后一次修改的时间。
st_ctime: 由操做系统报告的"ctime"。在某些系统上(如Unix)是最新的元数据更改的时间,在其它系统上(如Windows)是建立时间(详细信息参见平台的文档)。
'''



# sys模块
# sys模块是与python解释器交互的一个接口
'''
sys.argv           命令行参数List,第一个元素是程序自己路径            #作权限用
sys.exit(n)        退出程序,正常退出时exit(0)                         #经常使用
sys.version        获取Python解释程序的版本信息
sys.maxint         最大的Int值
sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform       返回操做系统平台名称
'''
# import sys
# # >python "2os&sys.py" egon somebody  #程序执行方式
# print(sys.argv)    #打印参数,0是"2os&sys.py"程序文件名字  1是egon 2是somebody
# name = sys.argv[1]
# password = sys.argv[2]
# if name == 'egon' and password == 'somebody':
#     print('继续执行程序')
# else:
#     sys.exit('登录失败')

# 添加环境变量
# import sys
# sys.path.append('/root/dir/file')


# 进度条
import sys

import time

def view_bar(num,total):
    rate = float(num) / total
    rate_num = int(rate * 100)
    r = '\r%s>%d%%' % ('='*num,rate_num)
    # \r回到当前行的首部位
    sys.stdout.write(r) # 相对比print,就是没有换行符
    # sys.stdout.flush() # 输出清空


if __name__ == '__main__':
    print( '\r%s>%d%%' % ('=',1))
    print( '\r%s>%d%%' % ('=',2))
    print( '\r%s>%d%%' % ('=',98))
    print( '\r%s>%d%%' % ('=',100))
    for i in range(1,101):
        time.sleep(0.3)
        view_bar(i,100)

# %% 2个百分号表明一个站位符
os&sys

 

# !/usr/bin/env python
# _*_coding:utf-8_*_
# Author:Joker


import time

# print(time.time())   # 1531982635.617672 时间戳 1970年开始计数的

# print(time.ctime())  # Thu Jul 19 14:45:44 2018,当前时间

# print(time.ctime(time.time()-86400)) # Wed Jul 18 14:49:26 2018 时间戳转化为字符串时间

# print(time.gmtime())
# time.struct_time(tm_year=2018, tm_mon=7, tm_mday=19, tm_hour=6, tm_min=50, tm_sec=15, tm_wday=3, tm_yday=200, tm_isdst=0)
# time_obj = time.gmtime()
# print(time_obj.tm_year,time_obj.tm_mon) # 2018 7 注意下day的值,周一是0,并且是utc时间

# print(time.gmtime(time.time()-86400)) # 将时间戳转换成struct_time格式
# time.struct_time(tm_year=2018, tm_mon=7, tm_mday=18, tm_hour=6, tm_min=53, tm_sec=37, tm_wday=2, tm_yday=199, tm_isdst=0)

# print(time.localtime()) # 本地时间,按照服务器的时区
# time.struct_time(tm_year=2018, tm_mon=7, tm_mday=19, tm_hour=14, tm_min=56, tm_sec=14, tm_wday=3, tm_yday=200, tm_isdst=0)

# time_obj = time.gmtime()
# print(time.mktime(time_obj)) # 时间对象转成时间戳 # 1531954699.0

# tm = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime()) # 将struct_time格式转化成指定的字符串格式
# print(tm) # 2018-07-19 15:02:11

# tm = time.strptime('2018-07-19','%Y-%m-%d') # 将字符串格式转化成struct_time格式
# print(tm)
# time.struct_time(tm_year=2018, tm_mon=7, tm_mday=19, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=200, tm_isdst=-1)




import datetime
# print(datetime.date.today()) # 2018-07-19,当前年月日

# print(datetime.date.fromtimestamp(time.time())) # 2018-07-19 将时间戳转换成日期格式

# print(datetime.datetime.now()) # 2018-07-19 15:10:00.874436 当前时间

# current_time = datetime.datetime.now()
# print(current_time.timetuple()) # 将字符串转换为struct_time格式
# time.struct_time(tm_year=2018, tm_mon=7, tm_mday=19, tm_hour=15, tm_min=11, tm_sec=30, tm_wday=3, tm_yday=200, tm_isdst=-1)

# str_to_date = datetime.datetime.strptime('09/10/12','%d/%m/%y')
# print(str_to_date) # 2012-10-09 00:00:00 将字符串转换成日期格式

# 时间加减
# current_time = datetime.datetime.now() # 当前时间
# print(datetime.datetime.now() + datetime.timedelta(days=10))
# 2018-07-29 15:15:42.874593 比如今+10天

# print(datetime.datetime.now() - datetime.timedelta(days=10))
# 2018-07-09 15:16:55.388891 比如今-10天

# print(datetime.datetime.now() - datetime.timedelta(hours=10))
# 2018-07-19 05:18:23.341908 比如今-10小时

# 时间替换
# current_time = datetime.datetime.now() # 当前时间
# print(current_time.replace(2200,2,2))
# 2200-02-02 15:20:34.209528

# 时间比较
# current_time = datetime.datetime.now() # 当前时间
# old_time = current_time.replace(2017,5)
# print(current_time > old_time) # True
time&datetime

 

# !/usr/bin/env python
# _*_coding:utf-8_*_
# Author:Joker



import shutil

# f1 = open('随便写的.txt',encoding='utf-8')
# f2 = open('lala','w',encoding='utf-8')

# shutil.copyfileobj(f1,f2) # 将文件内容拷贝到另外一个文件中


# shutil.copyfile('随便写的.txt','haha') # 拷贝


# shutil.copymode('随便写的.txt','haha') # 仅拷贝权限,内容.组,用户多是你拷贝时候的用户


# shutil.copystat('随便写的.txt','haha') # 拷贝状态信息


# shutil.copy('随便写的.txt','haha') # 拷贝文件和权限


# shutil.copy2('随便写的.txt','haha') # 拷贝文件和状态信息


# shutil.copytree('目录1','目录2') # 递归拷贝文件,目录名就能够


# shutil.rmtree('目录1') #删除目录,这里写当前目录名就能够


# shutil.move('file1','目录') # 目录名就能够


# shutil.make_archive(base_name=,format=)
# base_name 压缩包的文件名,也能够是压缩包的路径,若是只是文件名,则保存至当前目录,不然保存至指定路径
    # 如 WW,保存至当前目录
    # 如 /USER/WW 保存到/USER/目录

# format 压缩包种类,ZIP,TAR,BZTAR,GZTAR
# root_dir 要压缩的文件夹路径
# owner 用户,默认当前用户
# group 组,默认当前组
# logger 用于记录日志,一般是logging.Logger对象



# shutil.make_archive('shuti','zip','压缩文件的路径便可')




# ya
import zipfile
#
# z = zipfile.ZipFile('da.zip','w')
# z.write('lala')
# print('干点别的')
# z.write('haha')

# jie
z = zipfile.ZipFile('da.zip','w')
z.extractall()
z.close()


import tarfile

# 压缩
tar = tarfile.open('da.tar','w')
tar.add('绝对lujing', arcname='bbs2.zip')
tar.add('绝对lujing', arcname='cmdb.zip')
tar.close()

# 解压
tar = tarfile.open('your.tar','r')
tar.extractall()  # 可设置解压地址
tar.close()
shutil

 

#!/usr/bin/env python
#_*_coding:utf-8_*_

# 序列化模块
# 将本来的字典、列表等内容转换成一个字符串的过程就叫作序列化
'''
好比,咱们在python代码中计算的一个数据须要给另一段程序使用,那咱们怎么给?
如今咱们能想到的方法就是存在文件里,而后另外一个python程序再从文件里读出来。
可是咱们都知道,对于文件来讲是没有字典这个概念的,因此咱们只能将数据转换成字典放到文件中。
你必定会问,将字典转换成一个字符串很简单,就是str(dic)就能够办到了,为何咱们还要学习序列化模块呢?
没错序列化的过程就是从dic 变成str(dic)的过程。如今你能够经过str(dic),将一个名为dic的字典转换成一个字符串,
可是你要怎么把一个字符串转换成字典呢?
聪明的你确定想到了eval(),若是咱们将一个字符串类型的字典str_dic传给eval,就会获得一个返回的字典类型了。
eval()函数十分强大,可是eval是作什么的?e官方demo解释为:将字符串str当成有效的表达式来求值并返回计算结果。
BUT!强大的函数有代价。安全性是其最大的缺点。
想象一下,若是咱们从文件中读出的不是一个数据结构,而是一句"删除文件"相似的破坏性语句,那么后果实在不堪设设想。
而使用eval就要担这个风险。
因此,咱们并不推荐用eval方法来进行反序列化操做(将str转换成python中的数据结构)
'''
# 序列化的目的
# 一、以某种存储形式使自定义对象持久化;
# 二、将对象从一个地方传递到另外一个地方。
# 三、使程序更具维护性。
# 数据结构 --> 序列化 --> str
# str --> 反序列化 --> 数据结构

d = {'1':'v'}
print(str(d))
s = str(d)
print(eval(s),type(s))   #eval不安全,remove rm操做太危险

# json 不是python发明的,全部的语言都在用,语言之间用字符串传递
# json 字符串 字典 列表能够的
# json 模块提供四个功能:dumps,dump,loads,load

# 将PYTHON基本数据类型转化为字符串形式
import json
ret_s = json.dumps(d)
print(ret_s,type(ret_s))

# 将PYTHON字符串形式转化成基本数据类型
ret_d = json.loads(ret_s)
print(ret_d,type(ret_d))

import json
# li = "['alex','eric']" 报错,由于其余语言的缘由,''在其余语言里面是字符
li = '["alex","eric"]'
ret = json.loads(li)
print(ret,type(ret)) # ['alex', 'eric'] <class 'list'>

#注意字符串必须是一个双引号,单引号就会报错
f = open('json_file')
d_s = f.read()
print(json.loads(d_s))
f.close()

# 小结   内存操做
#dumps  结构化的数据类型转字符串
#loads  字符串转结构化数据类型  结构化数据类型中的全部字符串必须是双引号引用

# 写回文件 dump load 操做文件跟序列化的关系
f = open('json_file','w')
dic = {'k1':'v1','k2':'v2','k3':'v3'}
json.dump(dic,f)     # 先序列化,在写文件
# f.write(json.dumps(dic))  #是先dumps转成字符串在写入文件
f.close()

f = open('json_file')
dic2 = json.load(f)  # 打开文件,而后转化成数据类型,load在你打开过程当中帮你loads了
print(dic2,type(dic2)) #直接就是一个字典类型,不须要转化
f.close()




# pickle  全部数据类型均可以,可是只是Python自有的,并且是bytes(用于一种Python独特状态)
# json & pickle模块
# 用于序列化的两个模块
    # json,用于字符串 和 python数据类型间(列表,字典)进行转换
    # pickle,用于python特有的类型 和 python的数据类型间进行转换

# pickle模块提供了四个功能:dumps、dump(序列化,存)、loads(反序列化,读)、load  (不只能够序列化字典,列表...能够把python中任意的数据类型序列化)
# python 特有的元祖  会被json搞成列表
# set               json不支持
tu = {1,2,3,4}
# import json
# print(json.dumps(tu))  #json不支持,因此这里不支持
import pickle
print(pickle.dumps(tu))    #bytes类型
pik_b = pickle.dumps(tu)
print(pickle.loads(pik_b)) #转回来
li = [1,2,3,4,5]
pickle.dump(li,open('db','rb'))

ret = pickle.load(open('db','rb'))
print(ret,type(ret))  # [1,2,3,4,5] list

# shelve模块
# shelve也是python提供给咱们的序列化工具,比pickle用起来更简单一些。
# shelve只提供给咱们一个open方法,是用key来访问的,使用起来和字典相似
import shelve
f = shelve.open('shelve_file')
f['key'] = {'int':10, 'float':9.5, 'string':'Sample data'}  #直接对文件句柄操做,就能够存入数据
f.close()

import shelve
f1 = shelve.open('shelve_file')
existing = f1['key']  #取出数据的时候也只须要直接用key获取便可,可是若是key不存在会报错
f1.close()
print(existing)

#注意:这个模块有个限制,它不支持多个应用同一时间往同一个DB进行写操做。
# 因此当咱们知道咱们的应用若是只进行读操做,咱们可让shelve经过只读方式打开DB
import shelve   #只读模式,就不会影响写的人了
f = shelve.open('shelve_file', flag='r')
existing = f['key']
f.close()
print(existing)

#注意:因为shelve在默认状况下是不会记录待持久化对象的任何修改的,
# 因此咱们在shelve.open()时候须要修改默认参数,不然对象的修改不会保存。
import shelve
f1 = shelve.open('shelve_file')  #没有改
print(f1['key'])
f1['key']['new_value'] = 'this was not here before'
f1.close()

f2 = shelve.open('shelve_file', writeback=True)  #改了
print(f2['key'])
f2['key']['new_value'] = 'this was not here before'
f2.close()

# 小结:writeback方式有优势也有缺点。优势是减小了咱们出错的几率,而且让对象的持久化对用户更加的透明了;
# 但这种方式并非全部的状况下都须要,首先,使用writeback之后,shelf在open()的时候会增长额外的内存消耗,
# 而且当DB在close()的时候会将缓存中的每个对象都写入到DB,这也会带来额外的等待时间。
# 由于shelve没有办法知道缓存中哪些对象修改了,哪些对象没有修改,所以全部的对象都会被写入。
json&shelve

 

# !/usr/bin/env python
# _*_coding:utf-8_*_
# Author:Joker


import configparser

# 生成配置文件
# config = configparser.ConfigParser()
#
# config["DEFAULT"] = {'ServerAliveInterval': '45',
#                      'Compression': 'yes',
#                      'CompressionLevel': '9'}
#
# config['bitbucket.org'] = {}
# config['bitbucket.org']['User'] = 'hg'
# config['topsecret.server.com'] = {}
# topsecret = config['topsecret.server.com']
# topsecret['Host Port'] = '50022'  # mutates the parser
# topsecret['ForwardX11'] = 'no'  # same here
# config['DEFAULT']['ForwardX11'] = 'yes'
# with open('example.ini', 'w') as configfile:
#     config.write(configfile)



# 读取配置文件
conf = configparser.ConfigParser()
conf.read('example.ini')


print(conf.sections()) # 不会打印DEFAULT,打印节点
print(conf.defaults()) # OrderedDict([('compression', 'yes'), ('serveraliveinterval', '45'), ('compressionlevel', '9'), ('forwardx11', 'yes')])


print(conf['bitbucket.org']['user'])


# 增删改查
# secs = config.sections()
# print secs
# options = config.options('group2')
# print options

# item_list = config.items('group2')
# print item_list

# val = config.get('group1','key')
# val = config.getint('group1','key')

# ########## 改写 ##########
# sec = config.remove_section('group1')
# config.write(open('i.cfg', "w"))

# sec = config.has_section('wupeiqi')
# sec = config.add_section('wupeiqi')
# config.write(open('i.cfg', "w"))


# config.set('group2','k1',11111)
# config.write(open('i.cfg', "w"))

# config.remove_option('group2','age')
# config.write(open('i.cfg', "w"))
configparser

 

#随机数
import random
#1.随机小数
print(random.random())  #从0-1之间的小数
print(random.uniform(1,3)) #1-3之间的小数

#2.随机整数
l = []
l.append(str(random.randint(0,9)))  #0-9之间的随机数
l.append(str(random.randint(0,9)))
print(''.join(l))   #显示97
print(l)            #['9', '7']
print(random.randrange(1,4,2))  #也能够用布长来作,这是打印1-4之间的奇数1 3

#3.随机一个返回
print(random.choice([1,2,'b',4,'a',6])) #随机选择一个返回,[]()均可以

#4.随机多个返回,返回的个数为函数的第二个参数,本例中是返回3个
print(random.sample([1,2,'b',4,'a',6],3)) #返回3个,和以前的  返回的是列表

#5.打乱顺序
l = list(range(100))
print(l)   #正常顺序
random.shuffle(l)
print(l)   #顺序打乱

#写一个验证码
#首先要有数字,其次要有字母,一共4位,能够重复
#65-91是a-z,用chr()能够转成字母
#print(chr(90))
#普通版本
new_num_l = list(map(str,range(10)))  #['0','1'...'9']  #用来存数字
alph_l = [chr(i) for i in range(65,91)]  #列表推导式   用来存字母
new_num_l.extend(alph_l)  #包含字母和数字
ret_l = [random.choice(new_num_l) for i in range(4)] #取得重复随机 列表推导式
print(''.join(ret_l))       #由于是列表,因此join一下
ret = random.sample(new_num_l,4)  #取得不重复随机
print(''.join(ret))

# 写成函数
def myrandom():
    new_num_l = list(map(str,range(10)))
    alph_l = [chr(i) for i in range(97,123)]  #列表推导式
    new_num_l.extend(alph_l)
    ret_l = [random.choice(new_num_l) for i in range(4)]  #列表推导式
    return ''.join(ret_l)
print(myrandom())

# def suiji(num):
#     return [random.choice(list(map(str,range(10))).extend([chr(i) for i in range(97,123)])) for j in range(num)]
# x = suiji(4)
# print(x)
random

 

# !/usr/bin/env python
# _*_coding:utf-8_*_
# Author:Joker




# 用于加密相关操做

import hashlib


obj = hashlib.md5()

obj.update(bytes('joker',encoding='utf-8'))

ret = obj.hexdigest()

print(ret)  #  9facbf452def2d7efc5b5c48cdb837fa



# 加盐操做,本身的KEY

obj = hashlib.md5(bytes('happy',encoding='utf-8'))

obj.update(bytes('joker',encoding='utf-8'))

ret = obj.hexdigest()

print(ret)  #  c17ebd08acae8d7a822cec70da3fcf99
hashlib

 

#!/usr/bin/python env
#_*_coding:utf-8_*_

#collections模块的用法
'''
在内置数据类型(dict、list、set、tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter、deque、defaultdict、namedtuple和OrderedDict等。
1.namedtuple: 生成可使用名字来访问元素内容的tuple
2.deque: 双端队列,能够快速的从另一侧追加和推出对象
3.Counter: 计数器,主要用来计数
4.OrderedDict: 有序字典
5.defaultdict: 带有默认值的字典
'''

# 1.namedtuple (重点)
from collections import namedtuple
Ponit = namedtuple('Ponit',['x','y','z'])
p = Ponit(1,2,5)
print(p.x)
print(p.y)
print(p.z)

# 2.deque
'''
使用list存储数据时,按索引访问元素很快,可是插入和删除元素就很慢了,由于list是线性存储,数据量大的时候,插入和删除效率很低
deque是为了高效实现插入和删除操做的双向列表,适合用于队列和栈:
'''
from collections import deque
q = deque(['a', 'b', 'c'])
q.append('x')
q.appendleft('y')
# print(q)
#deque(['y', 'a', 'b', 'c', 'x'])
# deque除了实现list的append()和pop()外,还支持appendleft()和popleft(),这样就能够很是高效地往头部添加或删除元素

# 3.OrderedDict (重点)消耗内存
'''
使用dict时,Key是无序的。在对dict作迭代时,咱们没法肯定Key的顺序。
若是要保持Key的顺序,能够用OrderedDict:
'''
from collections import OrderedDict
d = dict([('a', 1), ('b', 2), ('c', 3)])
print(d)
#d dict的Key是无序的
#{'a': 1, 'c': 3, 'b': 2}
od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
print(od)
#od OrderedDict的Key是有序的
#OrderedDict([('a', 1), ('b', 2), ('c', 3)])

# 注意,OrderedDict的Key会按照插入的顺序排列,不是Key自己排序
od = OrderedDict()
od['z'] = 1
od['y'] = 2
od['x'] = 3
od.keys() # 按照插入的Key的顺序返回
#['z', 'y', 'x']

# 4.defaultdict (重点)(带默认的字典,就是当这个)
# 有以下值集合 [11,22,33,44,55,66,77,88,99,90...],将全部大于 66 的值保存至字典的第一个key中,将小于 66 的值保存至第二个key的值中。
# 普通代码,须要判断这个key,vales存在不存在
values = [11, 22, 33,44,55,66,77,88,99,90]
my_dict = {}
for value in  values:
    if value>66:
        if my_dict.get('k1'):
            my_dict['k1'].append(value)
        else:
            my_dict['k1'] = [value]
    else:
        if my_dict.get('k2'):
            my_dict['k2'].append(value)
        else:
            my_dict['k2'] = [value]

# 使用dict时,若是引用的Key不存在,就会抛出KeyError。若是但愿key不存在时,返回一个默认值,就能够用defaultdict:
# 进阶版本   会给返回默认的参数,用了匿名函数的原理
from collections import defaultdict
values = [11, 22, 33,44,55,66,77,88,99,90]
my_dict = defaultdict(list)
for value in  values:
    if value>66:
        my_dict['k1'].append(value)
    else:
        my_dict['k2'].append(value)
print(my_dict['k1'])

#匿名函数
from collections import defaultdict
def func():
    return 'N/A'
my_dict = defaultdict(func)
print(my_dict['k'])

# 5.Counter
# Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素做为key,
# 其计数做为value。计数值能够是任意的Interger(包括0和负数)。Counter类和其余语言的bags或multisets很类似。
from collections import Counter
c = Counter('abcdeabcdabcaba')
print(c)
# 输出:Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1})
# http://www.cnblogs.com/Eva-J/articles/7291842.html
print('aaab'.count('a'))
collections

 

# !/usr/bin/env python
# _*_coding:utf-8_*_
# Author:Joker



#!/usr/bin/env python
#_*_coding:utf-8_*_

#linux 上调用python脚本
#os.system输出命令结果到屏幕,返回命令执行状态
#os.popen("dir") 返回内存对象,须要单独去取一下
#os.popen("dir").read() 保存命令的执行结果输出,可是不返回执行状态
#

#py 2.7  from only linxu 2.7....
#commands   = = == =  commands.getstatusoutput("dir") 返回执行状态和结果
#print(res[0])   (res[1])


#subprocess  python 3.5 ___run
import subprocess
# subprocess.run(["df","-h"])
# subprocess.run(["df","-h","|","grep","sda1"]) 命令执行会报错,由于加上管道符他解决不了
# subprocess.run(["df -h | grep sda1",shell=True]) 不须要python解析这个字符串,传给linux本身去解析

#os.system  = = = subprocess.call("df -h",shell=True)输出命令结果到屏幕,返回命令执行状态
#subprocess.checkcall("df -h",shell=True)若是报错就抛出异常,也是返回状态
#subprocess.getstatusoutput("df -h",shell=True)返回执行状态和结果  ==== commands.getstatusoutput("dir")
#subprocess.getoutput("df -h",shell=True)返回结果= = =os.popen("dir")
#

#subprocess.Popen("ifconfig|grep 192",shell=True,subprocess.PIPE)  pipe 管道意思
#res.stdout.read()  标准输出
#subprocess.Popen("dddd",shell=True,subprocess.PIPE,stderr=subprocess.PIPE)
#res.stderr.read()  标准错误
#subprocess.Popen("sleep30:echo 'hello'",shell=True,subprocess.PIPE,stderr=subprocess.PIPE)
#print(res.poll())  这个是返回执行的状态,执行完了返回0没有执行返回None
#print(res.wait())  等待返回结果

#terminate()杀掉所启动的进程
#subprocess.Popen("sleep30:echo 'hello'",shell=True,subprocess.PIPE,stderr=subprocess.PIPE)
#res.terminate()
#res.stdout.read()  是没有结果的,由于在上一个命令进程杀掉了

#communicate()等待任务结束  忘了他吧
#subprocess.Popen(['python3'],shell=True,subprocess.PIPE,stderr=subprocess.PIPE,stdin=subprocess.PIPE)
#res.stdin.write(b"print(1)")
#res.stdin.write(b"print(2)")
#res.communicate()

#cwd新启动的shell环境默认在哪一个地方
#subprocess.Popen(['pwd'],shell=True,subprocess.PIPE,cwd="/tmp")
#res.stdout.read()

#subprocess 交互输入密码
#subprocess.Popen("sudo apt-get install vim",shell=True) 环境乱了
#echo "pwd" | sudo -S apt-get install vim    -S从标准输入读取密码
#subprocess.Popen("echo 'pwd' | sudo -S apt-get install vim ",shell=True) 经过python能够
subprocess

 

'''
1.字符组:[0-9][a-z][A-Z]
在同一个位置可能出现的各类字符组成了一个字符组,在正则表达式中用[]表示
字符分为不少类,好比数字、字母、标点等等。
假如你如今要求一个位置"只能出现一个数字",那么这个位置上的字符只能是0、一、2...9这10个数之一。
能够写成这种 [0-5a-eA-Z]  取范围的匹配

2.字符
.   匹配除换行符之外的任意字符
\w  匹配字母或数字或下划线
\s  匹配任意的空白符
\d  匹配数字
\n  匹配一个换行符
\t  匹配一个制表符
\b  匹配一个单词的结尾
^   匹配字符串的开始
$   匹配字符串的结尾
\W  匹配非字母或数字或下划线
\D  匹配非数字
\S  匹配非空白符
a|b 匹配字符a或字符b
()  匹配括号内的表达式,也表示一个组
[...]   匹配字符组中的字符
[^...]  匹配除了字符组中字符的全部字符

3.量词
量词  用法说明
*   重复零次或更屡次
+   重复一次或更屡次
?   重复零次或一次
{n} 重复n次
{n,}    重复n次或更屡次
{n,m}   重复n到m次

4. .^$
正则  待匹配字符   匹配结果     说明
海. 海燕海娇海东   海燕海娇海东 匹配全部"海."的字符
^海. 海燕海娇海东  海燕        只从开头匹配"海."
海.$ 海燕海娇海东  海东        只匹配结尾的"海.$"

5.*+?{}
正则      待匹配字符                   匹配结果                说明
李.?     李杰和李莲英和李二棍子     李杰/李莲/李二            ?表示重复零次或一次,即只匹配"李"后面一个任意字符 
李.*     李杰和李莲英和李二棍子     李杰和李莲英和李二棍子    *表示重复零次或屡次,即匹配"李"后面0或多个任意字符
李.+     李杰和李莲英和李二棍子     李杰和李莲英和李二棍子    +表示重复一次或屡次,即只匹配"李"后面1个或多个任意字符
李.{1,2} 李杰和李莲英和李二棍子     李杰和/李莲英/李二棍        {1,2}匹配1到2次任意字符

注意:前面的*,+,?等都是贪婪匹配,也就是尽量匹配,后面加?号使其变成惰性匹配
正则      待匹配字符                   匹配结果        说明
李.*?     李杰和李莲英和李二棍子       李/李/李         惰性匹配

6.字符集[][^]
正则                   待匹配字符                  匹配结果                说明
李[杰莲英二棍子]*      李杰和李莲英和李二棍子     李杰/李莲英/李二棍子     表示匹配"李"字后面[杰莲英二棍子]的字符任意次 
李[^和]*               李杰和李莲英和李二棍子     李杰/李莲英/李二棍子     表示匹配一个不是"和"的字符任意次
[\d]                   456bdha3                   4/5/6/3                  表示匹配任意一个数字,匹配到4个结果
[\d]+                  456bdha3                   456/3                    表示匹配任意个数字,匹配到2个结果

7.分组()或|和[^]
身份证号码是一个长度为15或18个字符的字符串,若是是15位则所有🈶️数字组成,首位不能为0;若是是18位,则前17位所有是数字,末位多是数字或x,下面咱们尝试用正则来表示:
正则                                待匹配字符                  匹配结果                说明
^[1-9]\d{13,16}[0-9x]$              110101198001017032          110101198001017032      表示能够匹配一个正确的身份证号
^[1-9]\d{13,16}[0-9x]$              1101011980010170            1101011980010170        表示也能够匹配这串数字,但这并非一个正确的身份证号码,它是一个16位的数字
^[1-9]\d{14}(\d{2}[0-9x])?$         1101011980010170            False                   如今不会匹配错误的身份证号了()表示分组,将\d{2}[0-9x]分红一组,就能够总体约束他们出现的次数为0-1次
^([1-9]\d{16}[0-9x]|[1-9]\d{14})$   110105199812067023          110105199812067023      表示先匹配[1-9]\d{16}[0-9x]若是没有匹配上就匹配[1-9]\d{14}

8.转义符\
在正则表达式中,有不少有特殊意义的是元字符,好比\d和\s等,若是要在正则中匹配正常的"\d"而不是"数字"就须要对"\"进行转义,变成'\\'。
在python中,不管是正则表达式,仍是待匹配的内容,都是以字符串的形式出现的,在字符串中\也有特殊的含义,自己还须要转义。因此若是匹配一次"\d",字符串中要写成'\\d',那么正则里就要写成"\\\\d",这样就太麻烦了。这个时候咱们就用到了r'\d'这个概念,此时的正则是r'\\d'就能够了。
正则                   待匹配字符                  匹配结果                说明
d                      \d                         False                   由于在正则表达式中\是有特殊意义的字符,因此要匹配\d自己,用表达式\d没法匹配
\\d                    \d                          True                    转义\以后变成\\,便可匹配
"\\\\d"                '\\d'                       True                    若是在python中,字符串中的'\'也须要转义,因此每个字符串'\'又须要转义一次
r'\\d'                  r'\d'                     True                    在字符串以前加r,让整个字符串不转义

9,贪婪匹配
贪婪匹配:在知足匹配时,匹配尽量长的字符串,默认状况下,采用贪婪匹配
正则                   待匹配字符                  匹配结果                说明
<.*>                   <script>...<script>         <script>...<script>     默认为贪婪匹配模式,会匹配尽可能长的字符串
<.*?>                   r'\d'                       <script>/<script>      加上?为将贪婪匹配模式转为非贪婪匹配模式,会匹配尽可能短的字符串

几个经常使用的非贪婪匹配Pattern
*? 重复任意次,但尽量少重复
+? 重复1次或更屡次,但尽量少重复
?? 重复0次或1次,但尽量少重复
{n,m}? 重复n到m次,但尽量少重复
{n,}? 重复n次以上,但尽量少重复

.*?的用法
. 是除换行符外任意字符
* 是取 0 至 无限长度
? 是非贪婪模式。
何在一块儿就是 取尽可能少的任意字符,通常不会这么单独写,他大多用在:
.*?x

就是取前面任意长度的字符,直到一个x出现
'''


# [] 中括号里面若是是特殊意义字符就会变成普通的,好比[.*?]
正则表达式
#!/usr/bin/python env
#_*_coding:utf-8_*_

import re
#re模块的用法

ret = re.findall('a', 'eva egon yuan')  # 返回全部知足匹配条件的结果,放在列表里
print(ret) #结果 : ['a', 'a']

ret = re.search('a', 'eva egon yuan').group()
print(ret) #结果 : 'a'
# 函数会在字符串内查找模式匹配,只到找到第一个匹配而后返回一个包含匹配信息的对象,该对象能够
# 经过调用group()方法获得匹配的字符串,若是字符串没有匹配,则返回None。

ret = re.match('a', 'abc').group()  # 同search,不过尽在字符串开始处进行匹配,若是没有GROUP只是对象
print(ret)
#结果 : 'a'

ret = re.split('[ab]', 'abcd')  # 先按'a'分割获得''和'bcd',在对''和'bcd'分别按'b'分割
print(ret)  # ['', '', 'cd']

ret = re.sub('\d', 'H', 'eva3egon4yuan4', 1)#将数字替换成'H',参数1表示只替换1个
print(ret) #evaHegon4yuan4

ret = re.subn('\d', 'H', 'eva3egon4yuan4')#将数字替换成'H',返回元组(替换的结果,替换了多少次)
print(ret)

obj = re.compile('\d{3}')  #将正则表达式编译成为一个 正则表达式对象,规则要匹配的是3个数字
ret = obj.search('abc123eeee') #正则表达式对象调用search,参数为待匹配的字符串
print(ret.group())  #结果 : 123

import re
ret = re.finditer('\d', 'ds3sy4784a')   #finditer返回一个存放匹配结果的迭代器
print(ret)  # <callable_iterator object at 0x10195f940>
print(next(ret).group())  #查看第一个结果
print(next(ret).group())  #查看第二个结果
print([i.group() for i in ret])  #查看剩余的左右结果

#注意:
#1 findall的优先级查询
import re

ret = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com')
print(ret)  # ['oldboy']     这是由于findall会优先把匹配结果组里内容返回,若是想要匹配结果,取消权限便可

ret = re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com')
print(ret)  # ['www.oldboy.com']

#2 split的优先级查询,规则,匹配内容,分割个数
ret=re.split("\d+","eva3egon4yuan")
print(ret) #结果 : ['eva', 'egon', 'yuan']

ret=re.split("(\d+)","eva3egon4yuan")
print(ret) #结果 : ['eva', '3', 'egon', '4', 'yuan']

#3 SPLIT有名分割,无名分割
ret = 'joker aa joker bb'
print(re.split('joker',ret,1))   # ['', ' aa joker bb']

print(re.split('j(oker)',ret,1)) # ['', 'oker', ' aa joker bb']

#在匹配部分加上()以后所切出的结果是不一样的,
#没有()的没有保留所匹配的项,可是有()的却可以保留了匹配的项,
#这个在某些须要保留匹配部分的使用过程是很是重要的。

#findall  #直接返回一个列表
    #正常的正则表达式
    #可是只会把分组里的显示出来

#search   #返回一个对象 .group()
#match    #返回一个对象 .group()
re模块

 

'''
默认状况下Python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,
这说明默认的日志级别设置为WARNING(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG),
默认的日志格式为日志级别:Logger名称:用户输出消息。
'''
# import logging
# logging.debug('debug message')
# logging.info('info message')
# logging.warning('warning message')
# logging.error('error message')
# logging.critical('critical message')


# 灵活配置日志级别,日志格式,输出位置:

import logging
logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S',
                    filename='test.log',
                    filemode='w')

logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')


# 配置参数
'''
logging.basicConfig()函数中可经过具体参数来更改logging模块默认行为,可用参数有:

filename:用指定的文件名建立FiledHandler,这样日志会被存储在指定的文件中。
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
format:指定handler使用的日志显示格式。
datefmt:指定日期时间格式。
level:设置rootlogger(后边会讲解具体概念)的日志级别
stream:用指定的stream建立StreamHandler。能够指定输出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。

format参数中可能用到的格式化串:
%(name)s Logger的名字
%(levelno)s 数字形式的日志级别
%(levelname)s 文本形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(module)s 调用日志输出函数的模块名
%(funcName)s 调用日志输出函数的函数名
%(lineno)d 调用日志输出函数的语句所在的代码行
%(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d 输出日志信息时的,自Logger建立以 来的毫秒数
%(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(thread)d 线程ID。可能没有
%(threadName)s 线程名。可能没有
%(process)d 进程ID。可能没有
%(message)s用户输出的消息

'''

# ***
'''
logging库提供了多个组件:Logger、Handler、Filter、Formatter。Logger对象提供应用程序可直接使用的接口,Handler发送日志到适当的目的地,
Filter提供了过滤日志信息的方法,Formatter指定日志显示格式。另外,能够经过:logger.setLevel(logging.Debug)设置级别,固然,也能够经过
fh.setLevel(logging.Debug)单对文件流设置某个级别。
'''
# logger对象配置
'''
import logging

logger = logging.getLogger()
# 建立一个handler,用于写入日志文件
fh = logging.FileHandler('test.log')

# 再建立一个handler,用于输出到控制台
ch = logging.StreamHandler()

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

fh.setFormatter(formatter)
ch.setFormatter(formatter)

logger.addHandler(fh) #logger对象能够添加多个fh和ch对象
logger.addHandler(ch)

logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')
'''
logging

 

一 paramiko模块的安装
在python3中
pip3 install paramiko

在python2中
pycrypto,因为 paramiko 模块内部依赖pycrypto,因此先下载安装pycrypto #在python2中
pip3 install pycrypto
pip3 install paramiko
注:若是在安装pycrypto2.0.1时发生以下错误
        command 'gcc' failed with exit status 1...
多是缺乏python-dev安装包致使
若是gcc没有安装,请事先安装gcc


二 SSHClient 连接执行批处理命令
2.1基于用户名密码链接:
import paramiko
# 建立SSH对象
ssh = paramiko.SSHClient()
# 容许链接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 链接服务器
ssh.connect(hostname='120.92.84.249', port=22, username='root', password='xxx')
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
result = stdout.read()
print(result.decode('utf-8'))
# 关闭链接
ssh.close()

2.2SSHClient 封装 Transport
import paramiko
transport = paramiko.Transport(('120.92.84.249', 22))
transport.connect(username='root', password='xxx')
ssh = paramiko.SSHClient()
ssh._transport = transport
stdin, stdout, stderr = ssh.exec_command('df')
res=stdout.read()
print(res.decode('utf-8'))
transport.close()
SSHClient 封装 Transport

2.3基于公钥密钥链接:
客户端文件名:id_rsa
服务端必须有文件名:authorized_keys(在用ssh-keygen时,必须制做一个authorized_keys,能够用ssh-copy-id来制做)
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/tmp/id_rsa')
# 建立SSH对象
ssh = paramiko.SSHClient()
# 容许链接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 链接服务器
ssh.connect(hostname='120.92.84.249', port=22, username='root', pkey=private_key)
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
result = stdout.read()
print(result.decode('utf-8'))
# 关闭链接
ssh.close()

2.4SSHClient 封装 Transport
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/tmp/id_rsa')
transport = paramiko.Transport(('120.92.84.249', 22))
transport.connect(username='root', pkey=private_key)
ssh = paramiko.SSHClient()
ssh._transport = transport
stdin, stdout, stderr = ssh.exec_command('df')
result=stdout.read()
print(result.decode('utf-8'))
transport.close()
SSHClient 封装 Transport

2.5基于私钥字符串进行链接
import paramiko
from io import StringIO
key_str = """-----BEGIN RSA PRIVATE KEY-----
MK7ydr+Q1+6/ujs6e8WsXt8HZMa/1khCVSbrf1MgACvZPSSSrDpVwaDTSjlRI4AL
-----END RSA PRIVATE KEY-----"""
private_key = paramiko.RSAKey(file_obj=StringIO(key_str))
transport = paramiko.Transport(('120.92.84.249', 22))
transport.connect(username='root', pkey=private_key)
ssh = paramiko.SSHClient()
ssh._transport = transport
stdin, stdout, stderr = ssh.exec_command('df')
result = stdout.read()
print(result.decode('utf-8'))
transport.close()

三 SFTPClient
用于链接远程服务器并执行上传下载
3.1基于用户名密码上传下
import paramiko
transport = paramiko.Transport(('120.92.84.249',22))
transport.connect(username='root',password='xxx')
sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put('/tmp/id_rsa', '/etc/test.rsa')
# 将remove_path 下载到本地 local_path
sftp.get('remove_path', 'local_path')
transport.close()

3.2基于公钥密钥上传下载
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/tmp/id_rsa')
transport = paramiko.Transport(('120.92.84.249', 22))
transport.connect(username='root', pkey=private_key )
sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put('/tmp/id_rsa', '/tmp/a.txt')
# 将remove_path 下载到本地 local_path
sftp.get('remove_path', 'local_path')
transport.close()
paramiko
'''
题目:简单主机批量管理工具
需求:
主机分组
主机信息配置文件用configparser解析
可批量执行命令、发送文件,结果实时返回,执行格式以下
batch_run -h h1,h2,h3 -g web_clusters,db_servers -cmd "df -h" 
batch_scp -h h1,h2,h3 -g web_clusters,db_servers -action put -local test.py -remote /tmp/ 
主机用户名密码、端口能够不一样
执行远程命令使用paramiko模块
批量命令需使用multiprocessing并发
'''
import paramiko
import os
cmdlist=[]
ftplist=[]

class instructions:
    def __init__(self,user,pwd,host,port):
        self.user=user
        self.pwd=pwd
        self.host=host
        self.port=port

    def conn(self):
        transport = paramiko.Transport((self.host,self.port))
        transport.connect(username=self.user,password=self.pwd)
        #ssh连接对象
        ssh = paramiko.SSHClient()
        ssh._transport = transport
        cmdlist.append(ssh)
        #ftp连接对象
        sftp = paramiko.SFTPClient.from_transport(transport)
        ftplist.append(sftp)

    def cmd(self,user_order):
        for ssh_i in cmdlist:
            stdin, stdout, stderr = ssh_i.exec_command(user_order)
            res = stdout.read()+stderr.read()
            print(res.decode('utf-8'))

    def ftp(self,client_file,server_file):
        for sftp_i in ftplist:
            sftp_i.put(client_file,server_file)

    def quit(self):
        for ssh_i in cmdlist:
            ssh_i.close()
        for sftp_i in ftplist: #不知道能不能关闭
            sftp_i.close()
        cmdlist.clear()
        ftplist.clear()

def ls():
    for x in os.listdir(os.getcwd()):
        if os.path.isfile(x):
            print(x)

if __name__ == '__main__':
    user='root'
    pwd='123456'
    host=['192.168.1.104','192.168.1.106']
    port=22

    while True:
        user_cmd=input('>>>:')
        if user_cmd == 'conn':
            for host_i in host:
                link=instructions(user,pwd,host_i,port)
                link.conn()
                print('%s-连接Ok' %host_i)
            while True:
                user_cmd = input('>>>:')
                user_cmd = user_cmd.split()
                if user_cmd[0] == 'ls':
                    ls()
                elif user_cmd[0] == 'cmd':
                    link.cmd(user_cmd[1])
                elif user_cmd[0] == 'put':
                    if os.path.isfile(user_cmd[1]):
                        link.ftp(user_cmd[1],user_cmd[2])
                    else:
                        print('没有找到该%s文件'%user_cmd[1])
                        continue
                elif user_cmd[0] == 'quit':
                    link.quit()
                    break
                else:
                    print('ls,cmd,put,quit')
                    continue
        else:
            print('首先应该先连接!conn')
            continue
        break
主机批量管理工具
相关文章
相关标签/搜索