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个百分号表明一个站位符
# !/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
# !/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()
#!/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没有办法知道缓存中哪些对象修改了,哪些对象没有修改,所以全部的对象都会被写入。
# !/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"))
#随机数 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)
# !/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
#!/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'))
# !/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能够
''' 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()
''' 默认状况下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') '''
一 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()
''' 题目:简单主机批量管理工具 需求: 主机分组 主机信息配置文件用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