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
主機批量管理工具
相關文章
相關標籤/搜索