04: python經常使用模塊

目錄:

1.1 時間模塊time() 與 datetime()     返回頂部

  一、 time()模塊中的重要函數html

函數node

描述python

asctime([tuple])linux

將時間元組轉換爲字符串git

localtime([secs])正則表達式

將秒數轉換爲日期元組(轉換成本國時區而不是utc時區)算法

mktime(tuple)shell

將時間元組轉換爲本地時間express

sleep(secs)django

休眠(不作任何事情)secs

strptime(string[, format])

將字符串解析爲時間元組

time()

獲取當前時間戳

time.gmtime()

將時間轉換成utc格式的元組格式

   二、time()模塊時間格式轉換

            

  三、time()模塊時間轉換

    1. 時間戳               1970年1月1日以後的秒,     即:time.time()

    2. 格式化的字符串    2014-11-11 11:11,           即:time.strftime('%Y-%m-%d')

    3. 結構化時間          元組包含了:年、日、星期等... time.struct_time    即:time.localtime()

import time
print(time.time())                              # 時間戳:1511166937.2178104
print(time.strftime('%Y-%m-%d'))                 # 格式化的字符串: 2017-11-20
print(time.localtime())                         # 結構化時間(元組): (tm_year=2017, tm_mon=11...)
print(time.gmtime())                            # 將時間轉換成utc格式的元組格式: (tm_year=2017, tm_mon=11...)

#1. 將結構化時間轉換成時間戳: 1511167004.0
print(time.mktime(time.localtime()))

#2. 將格字符串時間轉換成結構化時間 元組: (tm_year=2017, tm_mon=11...)
print(time.strptime('2014-11-11', '%Y-%m-%d'))

#3. 結構化時間(元組) 轉換成  字符串時間  :2017-11-20
print(time.strftime('%Y-%m-%d', time.localtime()))  # 默認當前時間

#4. 將結構化時間(元組) 轉換成英文字符串時間 : Mon Nov 20 16:51:28 2017
print(time.asctime(time.localtime()))

#5. 將時間戳轉成 英文字符串時間 : Mon Nov 20 16:51:28 2017
print(time.ctime(time.time()))
time()模塊時間轉換

  四、ctime和asctime區別

          1)ctime傳入的是以秒計時的時間戳轉換成格式化時間

          2)asctime傳入的是時間元組轉換成格式化時間

import time
t1 = time.time()
print(t1)               #1483495728.4734166
print(time.ctime(t1))   #Wed Jan  4 10:08:48 2017
t2 = time.localtime()
print(t2)               #time.struct_time(tm_year=2017, tm_mon=1, tm_mday=4, tm_hour=10, print(time.asctime(t2)) #Wed Jan  4 10:08:48 2017
ctime和asctime區別

   五、datetime

import datetime
#一、datetime.datetime獲取當前時間
print(datetime.datetime.now())
#二、獲取三天後的時間
print(datetime.datetime.now()+datetime.timedelta(+3))
#三、獲取三天前的時間
print(datetime.datetime.now()+datetime.timedelta(-3))
#四、獲取三個小時後的時間
print(datetime.datetime.now()+datetime.timedelta(hours=3))
#五、獲取三分鐘之前的時間
print(datetime.datetime.now()+datetime.timedelta(minutes = -3))

import datetime
print(datetime.datetime.now())                                   #2017-08-18 11:25:52.618873
print(datetime.datetime.now().date())                            #2017-08-18
print(datetime.datetime.now().strftime("%Y-%m-%d %H-%M-%S"))    #2017-08-18 11-25-52
datetime獲取時間
#一、datetime對象與str轉化
# datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
'2018-03-09 10:08:50'

# datetime.datetime.strptime('2016-02-22',"%Y-%m-%d")
datetime.datetime(2016, 2, 22, 0, 0)

#二、datetime對象轉時間元組
# datetime.datetime.now().timetuple()
time.struct_time(tm_year=2018, tm_mon=3, tm_mday=9,

#三、時間戳轉換成datetime對象
# datetime.datetime.fromtimestamp(1520561646.8906238)
datetime.datetime(2018, 3, 9, 10, 14, 6, 890624)
datetime時間轉換

  六、本地時間與utc時間相互轉換

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

import time
import datetime

def utc2local(utc_st):
    ''' 做用:將UTC時間裝換成本地時間
    :param utc_st: 傳入的是utc時間(datatime對象)
    :return:  返回的是本地時間 datetime 對象
    '''
    now_stamp = time.time()
    local_time = datetime.datetime.fromtimestamp(now_stamp)
    utc_time = datetime.datetime.utcfromtimestamp(now_stamp)
    offset = local_time - utc_time
    local_st = utc_st + offset
    return local_st

def local2utc(local_st):
    ''' 做用:將本地時間轉換成UTC時間
    :param local_st: 傳入的是本地時間(datatime對象)
    :return: 返回的是utc時間 datetime 對象
    '''
    time_struct = time.mktime(local_st.timetuple())
    utc_st = datetime.datetime.utcfromtimestamp(time_struct)
    return utc_st

utc_time = datetime.datetime.utcfromtimestamp(time.time())
# utc_time = datetime.datetime(2018, 5, 6, 5, 57, 9, 511870)        # 比北京時間晚了8個小時
local_time = datetime.datetime.now()
# local_time = datetime.datetime(2018, 5, 6, 13, 59, 27, 120771)    # 北京本地時間

utc_to_local = utc2local(utc_time)
local_to_utc = local2utc(local_time)
print utc_to_local       # 2018-05-06 14:02:30.650270     已經轉換成了北京本地時間
print local_to_utc       # 2018-05-06 06:02:30            轉換成北京當地時間
本地時間與utc時間相互轉換
from django.utils import timezone
from datetime import datetime

utc_time = timezone.now()
local_time = datetime.now()

#一、utc時間裝換成本地時間
utc_to_local = timezone.localtime(timezone.now())

#二、本地時間裝utc時間
local_to_utc = timezone.make_aware(datetime.now(), timezone.get_current_timezone())
django的timezone時間與本地時間轉換

  七、Python計算兩個日期之間天數

import datetime
d1 = datetime.datetime(2018,10,31)   # 第一個日期
d2 = datetime.datetime(2019,2,2)     # 第二個日期
interval = d2 - d1                   # 兩日期差距
print(interval.days)                 # 具體的天數
Python計算兩個日期之間天數

1.2 random()模塊     返回頂部

   一、random()模塊經常使用函數

函數

描述

random()

返回0<n<=1

getrandbits(n)

以長整形形式返回n個隨機位

uniform(a, b)

返回隨機實數n,其中a<=n<=b

randrange([start], stop, [step])

返回range(start,stop,step)中的隨機數

choice(seq)

從序列seq中返回隨意元素

shuffle(seq[, random])

原地指定序列seq(將有序列表變成無序的:洗牌)

sample(sea, n)

從序列seq中選擇n個隨機且獨立的元素

    二、random經常使用函數舉例

import random
#⒈ 隨機整數:
print(random.randint(0,99))             # 隨機選取0-99之間的整數
print(random.randrange(0, 101, 2))      # 隨機選取0-101之間的偶數

#⒉ 隨機浮點數:
print(random.random())                   # 0.972654134347
print(random.uniform(1, 10))             # 4.14709813772

#⒊ 隨機字符:
print(random.choice('abcdefg'))         # c
print(random.sample('abcdefghij',3))    # ['j', 'f', 'c']
random()函數使用舉例

  三、使用random實現四位驗證碼

import random
checkcode = ''
for i in range(4):
    current = random.randrange(0,4)
    if current == i:
        tmp = chr(random.randint(65,90))    #65,90表示全部大寫字母
    else:
        tmp = random.randint(0,9)
    checkcode += str(tmp)
print(checkcode)                            #運行結果: 851K
使用for循環實現
import random
import string
str_source = string.ascii_letters + string.digits
str_list = random.sample(str_source,7)

#['i', 'Q', 'U', 'u', 'A', '0', '9']
print(str_list)
str_final = ''.join(str_list)

#iQUuA09
print(str_final)            # 運行結果: jkFU2Ed
使用random.sample實現
>>> string.digits
'0123456789'
>>> string.ascii_lowercase
'abcdefghijklmnopqrstuvwxyz'

1.3 os模塊     返回頂部

import os
#1 當前工做目錄,即當前python腳本工做的目錄路徑
print(os.getcwd())    # C:\Users\admin\PycharmProjects\s14\Day5\test4

#2 當前腳本工做目錄;至關於shell下cd
os.chdir("C:\\Users\\admin\\PycharmProjects\\s14")
os.chdir(r"C:\Users\admin\PycharmProjects\s14")
print(os.getcwd())    # C:\Users\admin\PycharmProjects\s14

#3 返回當前目錄: ('.')
print(os.curdir)        # ('.')

#4 獲取當前目錄的父目錄字符串名:('..')
print(os.pardir)        # ('..')

#5 可生成多層遞歸目錄
os.makedirs(r'C:\aaa\bbb')         # 能夠發如今C盤建立了文件夾/aaa/bbb

#6 若目錄爲空,則刪除,並遞歸到上一級目錄,如若也爲空,則刪除,依此類推
os.removedirs(r'C:\aaa\bbb')    # 刪除全部空目錄

#7 生成單級目錄;至關於shell中mkdir dirname
os.mkdir(r'C:\bbb')        # 僅能建立單個目錄

#8 刪除單級空目錄,若目錄不爲空則沒法刪除,報錯;至關於shell中rmdir dirname
os.rmdir(r'C:\aaa')        # 僅刪除指定的一個空目錄

#9 列出指定目錄下的全部文件和子目錄,包括隱藏文件,並以列表方式打印
print(os.listdir(r"C:\Users\admin\PycharmProjects\s14"))

#10 刪除一個文件
os.remove(r'C:\bbb\test.txt')        # 指定刪除test.txt文件

#11 重命名文件/目錄
os.rename(r'C:\bbb\test.txt',r'C:\bbb\test00.bak')

#12 獲取文件/目錄信息
print(os.stat(r'C:\bbb\test.txt'))

#13 輸出操做系統特定的路徑分隔符,win下爲"\\",Linux下爲"/"
print(os.sep)                # \

#14 輸出當前平臺使用的行終止符,win下爲"\r\n",Linux下爲"\n"
print(os.linesep)

#15 輸出用於分割文件路徑的字符串
print(os.pathsep)                # ;  (分號)

#16 輸出字符串指示當前使用平臺。win->'nt'; Linux->'posix'
print(os.name)                # nt

#17 運行shell命令,直接顯示
os.system("bash command")

#18 獲取系統環境變量
print(os.environ)                # environ({'OS': 'Windows_NT', 'PUBLIC': ………….

#19 返回path規範化的絕對路徑
print(os.path.abspath(r'C:/bbb/test.txt'))    # C:\bbb\test.txt

#20 將path分割成目錄和文件名二元組返回
print(os.path.split(r'C:/bbb/ccc'))    # ('C:/bbb', 'ccc')

#21 返回path的目錄。其實就是os.path.split(path)的第一個元素
print(os.path.dirname(r'C:/bbb/ccc'))    # C:/bbb

#22 返回path最後的文件名。如何path以/或\結尾,那麼就會返回空值。即os.path.split(path)的第二個元素
print(os.path.basename(r'C:/bbb/ccc/ddd'))    # ddd

#23 若是path存在,返回True;若是path不存在,返回False
print(os.path.exists(r'C:/bbb/ccc/'))    # True

#24 若是path是絕對路徑,返回True        # True
print(os.path.isabs(r"C:\Users\admin\PycharmProjects\s14\Day5\test4"))

#25 若是path是一個存在的文件,返回True。不然返回False
print(os.path.isfile(r'C:/bbb/ccc/test2.txt'))        # True

#26 若是path是一個存在的目錄,則返回True。不然返回False
print(os.path.isdir(r'C:/bbb/ccc'))            # True

#28 返回path所指向的文件或者目錄的最後存取時間
print(os.path.getatime(r'C:/bbb/ccc/test2.txt'))        # 1483509254.9647143

#29 返回path所指向的文件或者目錄的最後修改時間
print(os.path.getmtime(r'C:/bbb/ccc/test2.txt'))        # 1483510068.746478

#30 不管linux仍是windows,拼接出文件路徑
put_filename = '%s%s%s'%(self.home,os. path.sep, filename)
#C:\Users\admin\PycharmProjects\s14\day10select版FTP\home
os模塊經常使用方法
import os

os.makedirs('C:/aaa/bbb/ccc/ddd',exist_ok=True)         # exist_ok=True:若是存在當前文件夾不報錯
path = os.path.join('C:/aaa/bbb/ccc','ddd',)
f_path = os.path.join(path,'file.txt')

with open(f_path,'w',encoding='utf8') as f:
    f.write('are you ok!!')
os命令建立文件夾: C:/aaa/bbb/ccc/ddd並寫入文件file1.txt
import os,sys
print(os.path.dirname( os.path.dirname( os.path.abspath(__file__) ) ))
BASE_DIR = os.path.dirname( os.path.dirname( os.path.abspath(__file__) ) )
sys.path.append(BASE_DIR)

# 代碼解釋:
# 要想導入其餘目錄中的函數,其實就是將其餘目錄的絕對路徑動態的添加到pyhton的環境變量中,這樣python解釋器就可以在運行時找到導入的模塊而不報錯:
# 而後調用sys模塊sys.path.append(BASE_DIR)就能夠將這條路徑添加到python環境變量中
將其餘目錄的絕對路徑動態的添加到pyhton的環境變量中

  一、os.popen獲取腳本執行結果

data = {'name':'aaa'}
import json
print json.dumps(data)
data.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import os,json

ret = os.popen('python data.py')
data = ret.read().strip()
ret.close()
data = json.loads(data)
print data  # {'name':'aaa'}
get_data.py

1.4 sys模塊     返回頂部

  一、 sys基本方法

    sys.argv          返回執行腳本傳入的參數

    sys.exit(n)                       退出程序,正常退出時exit(0)

    sys.version                           獲取Python解釋程序的版本信息

    sys.maxint                            最大的Int值

    sys.path                                返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值

    sys.platform                           返回操做系統平臺名稱

    sys.stdout.write('please:')

    val = sys.stdin.readline()[:-1]

  二、使用sys返回運行腳本參數

import sys
# C:\Users\tom\PycharmProjects\s14Review\day01>  python test01.py 1 2 3
print(sys.argv)         # 打印全部參數                 ['test01.py', '1', '2', '3']
print(sys.argv[1:])     # 獲取索引 1 日後的全部參數     ['1', '2', '3']
sys.argv返回執行腳本傳入的參數

1.5 tarfile用於將文件夾歸檔成 .tar的文件     返回頂部

import tarfile
# 將文件夾Day1和Day2歸檔成your.rar而且在歸檔文件夾中Day1和Day2分別變成bbs2.zip和ccdb.zip的壓縮文件
tar = tarfile.open('your.tar','w')
tar.add(r'C:\Users\admin\PycharmProjects\s14\Day1', arcname='bbs2.zip')
tar.add(r'C:\Users\admin\PycharmProjects\s14\Day2', arcname='cmdb.zip')
tar.close()

# 將剛剛的歸檔文件your.tar進行解壓解壓的內容是bbs2.zip和cmdb.zip壓縮文件而不是變成原有的文件夾
tar = tarfile.open('your.tar','r')
tar.extractall()  # 可設置解壓地址
tar.close()
tarfile使用

1.6 shutil 建立壓縮包,複製,移動文件     返回頂部

  注 :   shutil 對壓縮包的處理是調用 ZipFile 和 TarFile 兩個模塊來進行的
    做用: shutil 建立壓縮包並返回文件路徑(如:zip、tar),而且能夠複製文件,移動文件

import shutil
#1 copyfileobj()  將文件test11.txt中的內容複製到test22.txt文件中
f1 = open("test11.txt",encoding="utf-8")
f2 = open("test22.txt",'w',encoding="utf-8")
shutil.copyfileobj(f1,f2)

#2  copyfile()  直接指定文件名就可進行復制
shutil.copyfile("test11.txt",'test33.txt')

#3  shutil.copymode(src, dst) 僅拷貝權限。內容、組、用戶均不變

#4  shutil.copystat(src, dst)  拷貝狀態的信息,包括:mode bits, atime, mtime, flags
shutil.copystat('test11.txt','test44.txt')

#5  遞歸的去拷貝目錄中的全部目錄和文件,這裏的test_dir是一個文件夾,包含多級文件夾和文件
shutil.copytree("test_dir","new_test_dir")

#6  遞歸的去刪除目錄中的全部目錄和文件,這裏的test_dir是一個文件夾,包含多級文件夾和文件
shutil.rmtree("test_dir")

#7 shutil.move(src, dst)  遞歸的去移動文件
shutil.move('os_test.py',r'C:\\')

#8  shutil.make_archive(base_name, format,...) 建立壓縮包並返回文件路徑,例如:zip、tar
'''
   1. base_name: 壓縮包的文件名,也能夠是壓縮包的路徑。只是文件名時,則保存至當前目錄,不然保存至指定路徑,
        如:www                        =>保存至當前路徑
        如:/Users/wupeiqi/www =>保存至/Users/wupeiqi/
   2.  format: 壓縮包種類,「zip」, 「tar」, 「bztar」,「gztar」
   3. root_dir: 要壓縮的文件夾路徑(默認當前目錄)
   4. owner: 用戶,默認當前用戶
   5. group: 組,默認當前組
   6. logger: 用於記錄日誌,一般是logging.Logger對象

'''
#將C:\Users\admin\PycharmProjects\s14\Day4 的文件夾壓縮成 testaa.zip
shutil.make_archive("testaa","zip",r"C:\Users\admin\PycharmProjects\s14\Day4")
shutil使用

1.7 zipfile將文件或文件夾進行壓縮     返回頂部

import zipfile
#將文件main.py和test11.py壓縮成day5.zip的壓縮文件
z = zipfile.ZipFile('day5.zip', 'w')
z.write('main.py')
z.write("test11.txt")
z.close()

#將剛剛壓縮的day5.zip文件進行解壓成原文件
z = zipfile.ZipFile('day5.zip', 'r')
z.extractall()
z.close()
zipfile使用

1.8 shelve 模塊     返回頂部

  做用:shelve模塊是一個簡單的k,v將內存數據經過文件持久化的模塊,能夠持久化任何pickle可支持的python數據格式

import shelve
import datetime
#1 首先使用shelve將.py中定義的字典列表等讀取到指定文件shelve_test中,其實咱們可沒必要關心在文件中是怎樣存儲的
d = shelve.open('shelve_test')   #打開一個文件
info = {"age":22,"job":"it"}
name = ["alex","rain","test"]
d["name"] = name                  #持久化列表
d["info"] = info
d["date"] = datetime.datetime.now()
d.close()

#2 在這裏咱們能夠將剛剛讀取到 shelve_test文件中的內容重新獲取出來
d = shelve.open('shelve_test')   # 打開一個文件
print(d.get("name"))             # ['alex', 'rain', 'test']
print(d.get("info"))             # {'job': 'it', 'age': 22}
print(d.get("date"))             # 2017-11-20 17:54:21.223410
shelve持久化

1.9 json和pickle序列化     返回頂部

  一、json序列化

    1. 序列化 (json.dumps) :是將內存中的對象存儲到硬盤,變成字符串

    2. 反序列化(json.loads) : 將剛剛保存在硬盤中的內存對象重新加載到內存中

    json.dumps( data,ensure_ascii=False, indent=4)

#json序列化代碼
import json
info = {
    'name':"tom",
    "age" :"100"
}
f = open("test.txt",'w')
# print(json.dumps(info))
f.write(json.dumps(info))
f.close()
json序列化
#json反序列化代碼
import json
f = open("test.txt","r")
data = json.loads(f.read())
f.close()
print(data["age"])
json反序列化

  二、pickle序列化

    1. python的pickle模塊實現了python的全部數據序列和反序列化。基本上功能使用和JSON模塊沒有太大區別,方法也一樣是dumps/dump和loads/load

    2. 與JSON不一樣的是pickle不是用於多種語言間的數據傳輸,它僅做爲python對象的持久化或者python程序間進行互相傳輸對象的方法,所以它支持了python全部的數據類型。

#pickle序列化代碼
import pickle
info = {
    'name':"tom",
    "age" :"100"
}
f = open("test.txt",'wb')
f.write(pickle.dumps(info))
f.close()
pickle序列化
#pickle反序列化代碼
import pickle
f = open("test.txt","rb")
data = pickle.loads(f.read())
f.close()
print(data["age"])
pickle反序列化

  三、解決JSON不能夠序列化datetime類型

import json,datetime

class JsonCustomEncoder(json.JSONEncoder):
    def default(self, field):
        if isinstance(field, datetime.datetime):
            return field.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(field, datetime.date):
            return field.strftime('%Y-%m-%d')
        else:
            return json.JSONEncoder.default(self, field)

t = datetime.datetime.now()

print(type(t),t)
f = open('ttt','w')                              #指定將內容寫入到ttt文件中
f.write(json.dumps(t,cls=JsonCustomEncoder))      #使用時候只要在json.dumps增長個cls參數便可
解決json沒法序列化時間格式

    四、JSON和pickle模塊的區別

    1. JSON只能處理基本數據類型。pickle能處理全部Python的數據類型。

    2. JSON用於各類語言之間的字符轉換。pickle用於Python程序對象的持久化或者Python程序間對象網絡傳輸,但不一樣版本的Python序列化可能還有差別

1.10 hashlib 模塊     返回頂部

  一、用於加密相關的操做,代替了md5模塊和sha模塊,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

import hashlib

#1 ######## md5 ########
# 目的:實現對b"HelloIt's me" 這句話進行md5加密
m = hashlib.md5()            # 1)生成一個md5加密對象
m.update(b"Hello")          # 2)使用m對 b"Hello" 加密
m.update(b"It's me")        # 3) 使用m對 b"It's me"加密
print(m.hexdigest())         # 4) 最終加密結果就是對b"HelloIt's me"加密的md5值:5ddeb47b2f925ad0bf249c52e342728a

#2 ######## sha1 ########
hash = hashlib.sha1()
hash.update(b'admin')
print(hash.hexdigest())

#3 ######## sha256 ########
hash = hashlib.sha256()
hash.update(b'admin')
print(hash.hexdigest())

#4 ######## sha384 ########
hash = hashlib.sha384()
hash.update(b'admin')
print(hash.hexdigest())

#5 ######## sha512 ########
hash = hashlib.sha512()
hash.update(b'admin')
print(hash.hexdigest())
五種簡單加密方式

  二、以上加密算法雖然依然很是厲害,但時候存在缺陷,即:經過撞庫能夠反解。因此,有必要對加密算法中添加自定義key再來作加密。

######### hmac ########
import hmac
h = hmac.new(b"123456","真實要傳的內容".encode(encoding="utf-8"))
print(h.digest())
print(h.hexdigest())
# 注:hmac是一種雙重加密方法,前面是加密的內容,後面纔是真實要傳的數據信息
hmac添加自定義key加密

1.11 subprocess 模塊     返回頂部

   一、subprocess原理以及經常使用的封裝函數

    1.  運行python的時候,咱們都是在建立並運行一個進程。像Linux進程那樣,一個進程能夠fork一個子進程,並讓這個子進程exec另一個程序

    2. 在Python中,咱們經過標準庫中的subprocess包來fork一個子進程,並運行一個外部的程序。

    3. subprocess包中定義有數個建立子進程的函數,這些函數分別以不一樣的方式建立子進程,因此咱們能夠根據須要來從中選取一個使用

    4.  另外subprocess還提供了一些管理標準流(standard stream)和管道(pipe)的工具,從而在進程間使用文本通訊。

#一、返回執行狀態:0 執行成功
retcode = subprocess.call(['ping', 'www.baidu.com', '-c5'])

#二、返回執行狀態:0 執行成功,不然拋異常
subprocess.check_call(["ls", "-l"])

#三、執行結果爲元組:第1個元素是執行狀態,第2個是命令結果
>>> ret = subprocess.getstatusoutput('pwd')
>>> ret
(0, '/test01')

#四、返回結果爲 字符串 類型
>>> ret = subprocess.getoutput('ls -a')
>>> ret
'.\n..\ntest.py'


#五、返回結果爲'bytes'類型
>>> res=subprocess.check_output(['ls','-l'])
>>> res.decode('utf8')
'總用量 4\n-rwxrwxrwx. 1 root root 334 11月 21 09:02 test.py\n'
subprocess經常使用函數
subprocess.check_output(['chmod', '+x', filepath])
subprocess.check_output(['dos2unix', filepath])
將dos格式文件轉換成unix格式

  二、subprocess.Popen()

    1. 實際上,上面的幾個函數都是基於Popen()的封裝(wrapper),這些封裝的目的在於讓咱們容易使用子進程

    2. 當咱們想要更個性化咱們的需求的時候,就要轉向Popen類,該類生成的對象用來表明子進程

    3. 與上面的封裝不一樣,Popen對象建立後,主程序不會自動等待子進程完成。咱們必須調用對象的wait()方法,父進程纔會等待 (也就是阻塞block)

    4. 從運行結果中看到,父進程在開啓子進程以後並無等待child的完成,而是直接運行print。

#一、先打印'parent process'不等待child的完成
import subprocess
child = subprocess.Popen(['ping','-c','4','www.baidu.com'])
print('parent process')

#二、後打印'parent process'等待child的完成
import subprocess
child = subprocess.Popen('ping -c4 www.baidu.com',shell=True)
child.wait()
print('parent process')
child.wait()等待子進程執行

    child.poll()                                 # 檢查子進程狀態
    child.kill()                                  # 終止子進程
    child.send_signal()                   # 向子進程發送信號
    child.terminate()                       # 終止子進程

   三、subprocess.PIPE 將多個子進程的輸入和輸出鏈接在一塊兒

    1. subprocess.PIPE實際上爲文本流提供一個緩存區。child1的stdout將文本輸出到緩存區,隨後child2的stdin從該PIPE中將文本讀取走

    2. child2的輸出文本也被存放在PIPE中,直到communicate()方法從PIPE中讀取出PIPE中的文本。

    3. 注意:communicate()是Popen對象的一個方法,該方法會阻塞父進程,直到子進程完成

import subprocess
#下面執行命令等價於: cat /etc/passwd | grep root
child1 = subprocess.Popen(["cat","/etc/passwd"], stdout=subprocess.PIPE)
child2 = subprocess.Popen(["grep","root"],stdin=child1.stdout, stdout=subprocess.PIPE)
out = child2.communicate()               #返回執行結果是元組
print(out)
#執行結果: (b'root:x:0:0:root:/root:/bin/bash\noperator:x:11:0:operator:/root:/sbin/nologin\n', None)
分步執行cat /etc/passwd | grep root命
import subprocess

list_tmp = []
def main():
    p = subprocess.Popen(['ping', 'www.baidu.com', '-c5'], stdin = subprocess.PIPE, stdout = subprocess.PIPE)
    while subprocess.Popen.poll(p) == None:
        r = p.stdout.readline().strip().decode('utf-8')
        if r:
            # print(r)
            v = p.stdout.read().strip().decode('utf-8')
            list_tmp.append(v)
main()
print(list_tmp[0])
獲取ping命令執行結果

 1.12 logging模塊     返回頂部

  一、logging模塊的做用

    1. 不少程序都有記錄日誌的需求,而且日誌中包含的信息即有正常的程序訪問日誌,還可能有錯誤、警告等信息輸出

    2. python的logging模塊提供了標準的日誌接口,你能夠經過它存儲各類格式的日誌

    3. logging的日誌能夠分爲 debug()info()warning()error() and critical() 5個級別

Level

When it’s used

DEBUG

Detailed information, typically of interest only when diagnosing problems.

INFO

Confirmation that things are working as expected.

WARNING

An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected.

ERROR

Due to a more serious problem, the software has not been able to perform some function.

CRITICAL

A serious error, indicating that the program itself may be unable to continue running.

  二、日誌格式

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

用戶輸出的消息

  三、打印日誌和將日誌寫入文件小例子

import logging
#1 將日誌信息打印到屏幕中
logging.debug('debug info')
logging.info('info')
logging.warning('warning info')
logging.error('error info')
logging.critical('critical info')
將日誌打印到屏幕
import logging
logging.basicConfig(filename='test.log',level=logging.INFO,format='%(levelname)s  %(asctime)s %(message)s',datefmt='%Y-%m-%d %H:%M-%S')
logging.info('I am info')
# 記錄的文件的日誌格式:   INFO  2017-11-26 12:54-04 I am info
將日誌記錄到文件

  四、同時把log打印在屏幕和文件日誌裏

    1. Python 使用logging模塊記錄日誌涉及四個主要類

      1. logger提供了應用程序能夠直接使用的接口;

      2. handler將(logger建立的)日誌記錄發送到合適的目的輸出;

      3. filter提供了細度設備來決定輸出哪條日誌記錄;

      4. formatter決定日誌記錄的最終輸出格式

    2. 第一個主要類:logger

      1. 每一個程序在輸出信息以前都要得到一個Logger。

      2. Logger一般對應了程序的模塊名,好比聊天工具的圖形界面模塊能夠這樣得到它的Logger:LOG=logging.getLogger(」chat.gui」)

      3. 而核心模塊能夠這樣:LOG=logging.getLogger(」chat.kernel」)

      4. Logger.setLevel(lel):指定最低的日誌級別,低於lel的級別將被忽略。debug是最低的內置級別,critical爲最高

      5. Logger.addFilter(filt)、Logger.removeFilter(filt):添加或刪除指定的filter

      6. Logger.addHandler(hdlr)、Logger.removeHandler(hdlr):增長或刪除指定的handler

      7. Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical():能夠設置的日誌級別

    3. 第二個主要類:handler

      1. handler對象負責發送相關的信息到指定目的地,Python的日誌系統有多種Handler可使用。

      2. Handler能夠把信息輸出到控制檯,有些Logger能夠把信息輸出到文件,還有些 Handler能夠把信息發送到網絡上

      3. 若是以爲不夠用,還能夠編寫本身的Handler,能夠經過addHandler()方法添加多個多handler

        1Handler.setLevel(lel):指定被處理的信息級別,低於lel級別的信息將被忽略

        2Handler.setFormatter():給這個handler選擇一個格式

        3Handler.addFilter(filt)、Handler.removeFilter(filt):新增或刪除一個filter對象

    4. 每一個Logger能夠附加多個Handler,這裏介紹一些經常使用的

      1. logging.StreamHandler

        1. 使用這個Handler能夠向相似與sys.stdout或者sys.stderr的任何文件對象(file object)輸出信息。

        2. 它的構造函數是: StreamHandler([strm]) 其中strm參數是一個文件對象。默認是sys.stderr

      2. logging.FileHandler

        1. 和StreamHandler相似,用於向一個文件輸出日誌信息,不過FileHandler會幫你打開這個文件

        2. 它的構造函數是:

                                   ① FileHandler(filename[,mode])

                                   ② filename是文件名,必須指定一個文件名

                                   ③ mode是文件的打開方式。參見Python內置函數open()的用法。默認是’a',即添加到文件末尾。

      3. logging.handlers.RotatingFileHandler

        1. 這個Handler相似於上面的FileHandler,可是它能夠管理文件大小。

        2. 當文件達到必定大小以後,它會自動將當前日誌文件更名,而後建立 一個新的同名日誌文件繼續輸出

        3. 好比日誌文件是chat.log。當chat.log達到指定的大小以後,RotatingFileHandler自動把文件更名爲chat.log.1

        4. 不過,若是chat.log.1已經存在,會先把chat.log.1重命名爲chat.log.2。。。最後從新建立 chat.log,繼續輸出日誌信息

        5. 它的構造函數是:RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]])

                                   其中filename和mode兩個參數和FileHandler同樣

                                   maxBytes用於指定日誌文件的最大文件大小,若是maxBytes爲0,意味着日誌文件能夠無限大這時上面描述的重命名過程就不會發生

                                   backupCount用於指定保留的備份文件的個數。好比,若是指定爲2,當上面描述的重命名過程發生時,原有的chat.log.2並不會被改名,而是被刪除。

      4. logging.handlers.TimedRotatingFileHandler

        1. 這個Handler和RotatingFileHandler相似,不過,它沒有經過判斷文件大小來決定什麼時候從新建立日誌文件,而是間隔必定時間就 自動建立新的日誌文件。

        2. 過新的文件不是附加數字,而是當前時間。它的構造函數是:

                                   TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]])

                                   其中filename參數和backupCount參數和RotatingFileHandler具備相同的意義。

                                   interval是時間間隔。

                                   when參數是一個字符串。表示時間間隔的單位,不區分大小寫。它有如下取值:

                             注: S 秒;M 分;H 小時;D 天;W 每星期(interval==0時表明星期一);midnight 天天

import logging
#一、 create logger
logger1 = logging.getLogger('TEST-LOG')      #這裏的logger1是建立的logger實例名稱
logger1.setLevel(logging.DEBUG)                #這裏設置只有在DEBUG及其以上級別纔會記錄

#二、 create console handler and set level to debug
ch = logging.StreamHandler()               #StreamHandler括號內無參數表示默認是sys.stderr
ch.setLevel(logging.DEBUG)                   #指定只有在DEBUG級別及以上的纔會打印到屏幕

#三、 create file handler and set level to warning
fh = logging.FileHandler("access.log",encoding="utf-8")    #與StreamHandler相似可是必須指定記錄日誌文件名
fh.setLevel(logging.WARNING)                                 #指定在WARNING級別及以上的纔會記錄到文件中

#四、 create formatter                    #指定記錄日誌的格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

#五、 add formatter to ch and fh
ch.setFormatter(formatter)                #ch爲剛剛建立的StreamHandler方法這裏指定使用formatter的格式
fh.setFormatter(formatter)                #fh爲剛剛建立的FileHandler方發使用剛建立的formatter日誌格式

#六、 add ch and fh to logger
logger1.addHandler(ch)                    #將剛剛建立的StreamHandler方法添加到剛剛新建的日誌實例logger1中
logger1.addHandler(fh)                    #將剛剛建立的FileHandler方法添加到剛剛新建的日誌實例logger1中

#七、 'application' code
logger1.debug('debug message')
logger1.info('info message')
logger1.warn('warn message')
logger1.error('error message')
logger1.critical('critical message')

# 運行結果:打印在屏幕中的信息是下面五條
# 2017-01-07 09:32:08,478 - TEST-LOG - DEBUG - debug message
# 2017-01-07 09:32:08,479 - TEST-LOG - INFO - info message
# 2017-01-07 09:32:08,479 - TEST-LOG - WARNING - warn message
# 2017-01-07 09:32:08,479 - TEST-LOG - ERROR - error message
# 2017-01-07 09:32:08,480 - TEST-LOG - CRITICAL - critical message
# 記錄到access.log的文件內容是這裏的三條
# 2017-01-08 12:21:26,398 - TEST-LOG - WARNING - warn message
# 2017-01-08 12:21:26,398 - TEST-LOG - ERROR - error message
# 2017-01-08 12:21:26,398 - TEST-LOG - CRITICAL - critical message
同時把log打印在屏幕和文件日誌裏
import logging

from logging import handlers

logger = logging.getLogger(__name__)

log_file = "timelog.log"

#一、根據日誌文件大小切分:當文件大於10字節就會建立一個timelog.log.1 這樣名字的文件存放後續日誌
# fh = handlers.RotatingFileHandler(filename=log_file,maxBytes=10,backupCount=3)

#二、根據時間間隔切分: 每次間隔5秒就會從新建立一個timelog.log.2017-11-21_15-09-46 這樣名字的文件存放後續日誌
fh = handlers.TimedRotatingFileHandler(filename=log_file,when="S",interval=5,backupCount=3)

formatter = logging.Formatter('%(asctime)s %(module)s:%(lineno)d %(message)s')

fh.setFormatter(formatter)

logger.addHandler(fh)

logger.warning("test1")
logger.warning("test1")

# 運行結果:
#1. 根據日誌文件大小切分:當存放日誌的文件大於10字節就會重新建立新文件存放
#2. 根據時間間隔切分: 每隔5秒就會自動建立一個新文件存放
log日誌自動截斷代碼展現

  五、項目使用舉例:記錄錯誤日誌和運行日誌

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

import os
import logging
from config import settings


class Logger(object):
    __instance = None

    def __init__(self):
        self.run_log_file = settings.RUN_LOG_FILE
        self.error_log_file = settings.ERROR_LOG_FILE
        self.run_logger = None
        self.error_logger = None

        self.initialize_run_log()
        self.initialize_error_log()

    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance = object.__new__(cls, *args, **kwargs)
        return cls.__instance

    @staticmethod
    def check_path_exist(log_abs_file):
        log_path = os.path.split(log_abs_file)[0]
        if not os.path.exists(log_path):
            os.mkdir(log_path)

    def initialize_run_log(self):
        self.check_path_exist(self.run_log_file)
        file_1_1 = logging.FileHandler(self.run_log_file, 'a', encoding='utf-8')
        fmt = logging.Formatter(fmt="%(asctime)s - %(levelname)s :  %(message)s")
        file_1_1.setFormatter(fmt)
        logger1 = logging.Logger('run_log', level=logging.INFO)
        logger1.addHandler(file_1_1)
        self.run_logger = logger1

    def initialize_error_log(self):
        self.check_path_exist(self.error_log_file)
        file_1_1 = logging.FileHandler(self.error_log_file, 'a', encoding='utf-8')
        fmt = logging.Formatter(fmt="%(asctime)s  - %(levelname)s :  %(message)s")
        file_1_1.setFormatter(fmt)
        logger1 = logging.Logger('run_log', level=logging.ERROR)
        logger1.addHandler(file_1_1)
        self.error_logger = logger1

    def log(self, message, mode=True):
        """
        寫入日誌
        :param message: 日誌信息
        :param mode: True表示運行信息,False表示錯誤信息
        :return:
        """
        if mode:
            self.run_logger.info(message)
        else:
            self.error_logger.error(message)
lib/log.py
# 錯誤日誌
ERROR_LOG_FILE = os.path.join(BASEDIR, "log", 'error.log')
# 運行日誌
RUN_LOG_FILE = os.path.join(BASEDIR, "log", 'run.log')
settings.py
from lib.log import Logger
Logger().log('成功建立',True)   # 運行日誌
Logger().log('建立失敗',False)  # 錯誤日誌
run.py 記錄日誌

 1.13 paramiko使用     返回頂部

    在windows中安裝paramiko:   pip3 install paramiko

  一、linuxscp命令的使用

       ssh root@10.1.0.51            #ssh遠程登陸

       scp -rp aa.txt  root@10.1.0.50:/tmp/                  #將本地aa.txt文件複製到10.1.0.50的/tmp文件夾中

  二、Paramiko模塊做用

    1)若是須要使用SSH從一個平臺鏈接到另一個平臺,進行一系列的操做時,

      好比:批量執行命令,批量上傳文件等操做,paramiko是最佳工具之一。

    2)paramiko是用python語言寫的一個模塊,遵循SSH2協議,支持以加密和認證的方式,進行遠程服務器的鏈接

    3)因爲使用的是python這樣的可以跨平臺運行的語言,因此全部python支持的平臺,如Linux, Solaris, BSD,MacOS X, Windows等,paramiko均可以支持

    4)若是須要使用SSH從一個平臺鏈接到另一個平臺,進行一系列的操做時,paramiko是最佳工具之一

    5)如今若是須要從windows服務器上下載Linux服務器文件:

      a. 使用paramiko能夠很好的解決以上問題,它僅須要在本地上安裝相應的軟件(python以及PyCrypto)
      b. 對遠程服務器沒有配置要求,對於鏈接多臺服務器,進行復雜的鏈接操做特別有幫助。

  三、paramiko基於用戶名密碼鏈接

import paramiko

# 1 建立SSH對象
ssh = paramiko.SSHClient()
# 2 容許鏈接不在know_hosts文件中的主機
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 3 鏈接服務器
ssh.connect(hostname='1.1.1.3', port=22, username='root', password='chnsys@2016')

# 4 執行命令                                         #stdin標準輸入: 本身輸入的命令
stdin, stdout, stderr = ssh.exec_command('pwd')      # stdout標準輸出:  命令執行結果
# 5 獲取命令結果                                     #stderr標準錯誤:  命令執行報錯的結果
res, err = stdout.read(), stderr.read()
result = res if res else err
print(result.decode())                              #運行結果: /root

# 6 關閉鏈接
ssh.close()
遠程執行命令
import paramiko

#1 鏈接客戶端
transport = paramiko.Transport(('10.1.0.50',22))
transport.connect(username='root',password='chnsys@2016')

#2 定義與客戶端交互    將剛剛定義的transport當參數傳遞給他
sftp = paramiko.SFTPClient.from_transport(transport)
#3 將location.py 上傳至服務器 /tmp/test.py
sftp.put(r'C:\bbb\file.txt', '/tmp/file.txt')

#4 將remove_path 下載到本地 local_path
sftp.get('/tmp/file.txt',r'C:\bbb\file.txt')

#5 關閉鏈接
transport.close()
SFTPClient實現對Linux服務器上傳和下載

  四、在兩臺Linux中演示無密碼ssh登錄對方

    一、使用ssh-copy-id命令將公鑰copy到被管理服務器中(法1:簡單)

      1)操做目的:在10.1.0.50的tom用戶下生成祕鑰對,將生成的私鑰用ssh-copy-id拷貝給10.1.0.51的root用戶,那麼root用戶就可使用ssh root@10.1.0.51 遠程登錄了

[tom@localhost .ssh]$ ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/home/tom/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/tom/.ssh/id_rsa.
Your public key has been saved in /home/tom/.ssh/id_rsa.pub.
ssh-keygen生成祕鑰

      2)執行完上面命令後再 /home/tom/.ssh 文件夾下生成了公鑰私鑰連個文件:  id_rsa  id_rsa.pub

      3)將在10.1.0.50中生成的公鑰複製到10.1.0.51的root加目錄下:

         ssh-copy-id root@10.1.0.51

      4)執行完成後就會在10.1.0.51中生成 /home/zhangsan/.ssh/ authorized_keys 文件

      5)此時輸入: ssh root@10.1.0.51       就能夠直接不用密碼登錄了

    二、手動建立祕鑰並手動copy到被管理服務器(法2:較複雜)

      1)使用10.1.0.51在不輸入密碼的狀況下ssh連接到10.1.0.50,使用10.1.0.50的tom用戶身份進行登陸

      2)在 10.1.0.51上建立用於認證的祕鑰對

[root@localhost /]# ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.        #存放私鑰 的路徑
Your public key has been saved in /root/.ssh/id_rsa.pub.        #存放公約 的路徑
注:將10.1.0.51上生成的密鑰對中的公鑰放到10.1.0.50的服務器tom用戶家目錄/home/tom/.ssh/authorized_keys 中,就能夠在10.1.0.51中無密碼登錄10.1.0.50了
ssh-keygen生成祕鑰對

      3)在10.1.0.51中生成的私鑰路徑:cat  ~/.ssh/id_rsa.pub

      4)在被登陸服務器中建立用戶tom,將剛剛在10.1.0.51上生成的私鑰內容放到10.1.0.50的/home/tom/.ssh/authorized_keys中,

      5)新建立用戶沒用ssh登陸過期沒有,能夠手動建立

一、mkdir /home/tom/.ssh                                               #建立/home/tom/.ssh目錄

二、chmod 700 /home/tom/.ssh/                                     #將目錄權限改成 700

三、touch /home/tom/.ssh/authorized_keys                              #建立/home/tom/.ssh/authorized_keys文件

四、chmod 600 /home/tom/.ssh/authorized_keys                     #將文件權限改成600

五、將10.1.0.51的公鑰文件粘貼到10.1.0.50的/home/tom/.ssh/authorized_keys中
手動建立.ssh中的文件

      6)完成上面幾步後就能夠在10.1.0.51上無密碼登錄10.1.0.50了

      7)登錄命令:  ssh tom@10.1.0.50

  五、paramiko基於公鑰密鑰鏈接:(ssh_rsa)

    1.  操做目的:在10.1.0.50中生成公鑰和私鑰,而後將生成的公鑰放到10.1.0.51的winuser的/home/zhangsan/.ssh/ authorized_keys 目錄下

    2.  第一步:在10.1.0.50中建立anyuser,在10.1.0.51中建立winuser

    3.  在10.1.0.50中使用anyuser登錄,而後生成公鑰和私鑰

[anyuser@localhost ~]$ ssh-keygen 
Generating public/private rsa key pair.

Enter file in which to save the key (/home/anyuser/.ssh/id_rsa): Created directory '/home/anyuser/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/anyuser/.ssh/id_rsa.
Your public key has been saved in /home/anyuser/.ssh/id_rsa.pub.
anyuser生成祕鑰對

    4. 將在10.1.0.50中生成的公鑰複製到10.1.0.51的winuser目錄下:    ssh-copy-id winuser@10.1.0.51

    5. 執行完ssh-copy-id命令後就能夠看到在10.1.0.51中新加了這樣的目錄和文件/home/zhangsan/.ssh/ authorized_keys   # authorized_keys就是剛剛在10.1.0.50中生成的私鑰

    6. 將10.1.0.50中生成祕鑰文件內容放到windows的PyCharm運行文件同目錄,隨便命名爲:id_rsa50.txt

import paramiko

# 1 指定公鑰所在本地的路徑
private_key = paramiko.RSAKey.from_private_key_file('id_rsa50.txt')

# 2 建立SSH對象
ssh = paramiko.SSHClient()
# 3 容許鏈接不在know_hosts文件中的主機
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 4 鏈接服務器
ssh.connect(hostname='10.1.0.51', port=22, username='winuser', pkey=private_key)

# 5 執行命令
stdin, stdout, stderr = ssh.exec_command('pwd')  # stdout標準輸出:  命令執行結果
# 6 獲取命令結果                                          #stderr標準錯誤:  命令執行報錯的結果
res, err = stdout.read(), stderr.read()
result = res if res else err
print(result.decode())
# 7 關閉鏈接
ssh.close()
用PyCharm基於公鑰密鑰執行命令
import paramiko
#1 指定公鑰所在本地的路徑
private_key = paramiko.RSAKey.from_private_key_file('id_rsa50.txt')

#2 鏈接客戶端
transport = paramiko.Transport(('10.1.0.51', 22))
transport.connect(username='winuser', pkey=private_key )
#3 定義與客戶端交互
sftp = paramiko.SFTPClient.from_transport(transport)

#4上傳 將本地test1.py 上傳至服務器 /tmp/test1.py
sftp.put('test1.py', '/tmp/test1.py')

#5下載 將服務器/tmp/test1.py文件 下載到本地C:\bbb\test1.txt
sftp.get('/tmp/test1.py', r'C:\bbb\test1.txt')

transport.close()
用PyCharm基於公鑰密鑰上傳下載

 1.14 re模塊     返回頂部

   一、經常使用正則表達式符號

    ⒈通配符( .

      做用:點(.)能夠匹配除換行符之外的任意一個字符串

      例如:‘.ython’ 能夠匹配‘aython’ ‘bython’ 等等,但只能匹配一個字符串

    ⒉轉義字符( \

      做用:能夠將其餘有特殊意義的字符串以本來意思表示

      例如:‘python.org’ 由於字符串中有一個特殊意義的字符串(.)因此若是想將其按照普通意義就必須使用這樣表示:  ‘python\.org’ 這樣就只會匹配‘python.org’ 了

      注:若是想對反斜線(\)自身轉義可使用雙反斜線(\\)這樣就表示 ’\’

    ⒊字符集

      做用:使用中括號來括住字符串來建立字符集,字符集可匹配他包括的任意字串

        ①‘[pj]ython’ 只可以匹配‘python’  ‘jython’

         ‘[a-z]’ 可以(按字母順序)匹配a-z任意一個字符

        ‘[a-zA-Z0-9]’ 能匹配任意一個大小寫字母和數字    

        ‘[^abc]’ 能夠匹配任意除a,b和c 以外的字符串

    管道符

      做用:一次性匹配多個字符串

      例如:’python|perl’ 能夠匹配字符串‘python’ 和 ‘perl’

    ⒌可選項和重複子模式(在子模式後面加上問號?)

      做用:在子模式後面加上問號,他就變成可選項,出現或者不出如今匹配字符串中都是合法的

      例如:r’(aa)?(bb)?ccddee’ 只能匹配下面幾種狀況

         ‘aabbccddee’

         ‘aaccddee’

         ‘bbccddee’

         ‘ccddee’

    ⒍字符串的開始和結尾

            ‘w+’ 匹配以w開通的字符串

            ‘^http’ 匹配以’http’ 開頭的字符串

          ‘ $com’ 匹配以‘com’結尾的字符串

    7.最經常使用的匹配方法

          \d     匹配任何十進制數;它至關於類 [0-9]。
          \D     匹配任何非數字字符;它至關於類 [^0-9]。
          \s     匹配任何空白字符;它至關於類 [ fv]。
          \S     匹配任何非空白字符;它至關於類 [^ fv]。
          \w     匹配任何字母數字字符;它至關於類 [a-zA-Z0-9_]。
          \W     匹配任何非字母數字字符;它至關於類 [^a-zA-Z0-9_]。

          \w*    匹配全部字母字符

          \w+    至少匹配一個字符

 1 '.'         默認匹配除\n以外的任意一個字符,若指定flag DOTALL,則匹配任意字符,包括換行
 2 '^'         匹配字符開頭,若指定flags MULTILINE,這種也能夠匹配上(r"^a","\nabc\neee",flags=re.MULTILINE)
 3 '$'         匹配字符結尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也能夠
 4 '*'         匹配*號前的字符0次或屢次,re.findall("ab*","cabb3abcbbac")  結果爲['abb', 'ab', 'a']
 5 '+'         匹配前一個字符1次或屢次,re.findall("ab+","ab+cd+abb+bba") 結果['ab', 'abb']
 6 '?'         匹配前一個字符1次或0次
 7 '{m}'       匹配前一個字符m次
 8 '{n,m}'     匹配前一個字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 結果'abb', 'ab', 'abb']
 9 '|'         匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 結果'ABC'
10 '(...)'     分組匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 結果 abcabca456c
11  
12 '\A'       只從字符開頭匹配,re.search("\Aabc","alexabc") 是匹配不到的
13 '\Z'       匹配字符結尾,同$
14 '\d'       匹配數字0-9
15 '\D'       匹配非數字
16 '\w'       匹配[A-Za-z0-9]
17 '\W'       匹配非[A-Za-z0-9]
18 's'        匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 結果 '\t'
19 \b           匹配一個單詞邊界,也就是指單詞和空格間的位置,如,「er\b」能夠匹配「never」中的「er」,但不能匹配「verb」中的「er」
20 \B           匹配非單詞邊界。「er\B」能匹配「verb」中的「er」,但不能匹配「never」中的「er」
re模塊更詳細表達式符號

  二、re模塊經常使用函數

compile(pattern[, flags])

根據正則表達式字符串建立模式對象

search(pattern, string[, flags])

在字符串中尋找模式

match(pattern, 經常使用模塊[, flags])

在字符串的開始處匹配模式

split(pattern, string[, maxsplit=0])

根據模式的匹配項來分割字符串

findall(pattern, string)

列出字符串中模式的全部匹配項並以列表返回

sub(pat, repl, string[, count=0])

將字符串中全部pat的匹配項用repl替換

escape(string)

將字符串中全部特殊正則表達式字符轉義

    ⒈ re.compile(pattern[, flags])

        1)把一個正則表達式pattern編譯成正則對象,以即可以用正則對象的match和search方法

        2)用了re.compile之後,正則對象會獲得保留,這樣在須要屢次運用這個正則對象的時候,效率會有較大的提高

 import re
mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
ret = re.match(mobile_re,'18538762511')
print(ret)            # <_sre.SRE_Match object; span=(0, 11), match='18538652511'>
re.compile使用

    ⒉ search(pattern, string[, flags]) match(pattern, string[, flags])

        1)match :只從字符串的開始與正則表達式匹配,匹配成功返回matchobject,不然返回none;

        2)search :將字符串的全部字串嘗試與正則表達式匹配,若是全部的字串都沒有匹配成功,返回none,不然返回matchobject;

import re
a =re.match('www.bai', 'www.baidu.com')
b = re.match('bai', 'www.baidu.com')
print(a.group())                                # www.bai
print(b)                                        # None

# 不管有多少個匹配的只會匹配一個
c = re.search('bai', 'www.baidubaidu.com')
print(c)                                        # <_sre.SRE_Match object; span=(4, 7), match='bai'>
print(c.group())                                # bai
match與search使用比較

    ⒊ split(pattern, string[, maxsplit=0])

        做用:將字符串以指定分割方式,格式化成列表

import re
text = 'aa 1bb###2cc3ddd'
print(re.split('\W+', text))        # ['aa', '1bb', '2cc3ddd']
print(re.split('\W', text))          # ['aa', '1bb', '', '', '2cc3ddd']
print(re.split('\d', text))           # ['aa ', 'bb###', 'cc', 'ddd']
print(re.split('#', text))            # ['aa 1bb', '', '', '2cc3ddd']
print(re.split('#+', text))          # ['aa 1bb', '2cc3ddd']
split使用

    ⒋ findall(pattern, string)

        做用:正則表達式 re.findall 方法可以以列表的形式返回能匹配的子串

import re
p = re.compile(r'\d+')
print(p.findall('one1two2three3four4'))             # ['1', '2', '3', '4']
print(re.findall('o','one1two2three3four4'))        # ['o', 'o', 'o']
print(re.findall('\w+', 'he.llo, wo#rld!'))         # ['he', 'llo', 'wo', 'rld']
findall使用

    ⒌ sub(pat, repl, string[, count=0])

        1)替換,將string裏匹配pattern的部分,用repl替換掉,最多替換count次而後返回替換後的字符串

        2)若是string裏沒有能夠匹配pattern的串,將被原封不動地返回

        3)repl能夠是一個字符串,也能夠是一個函數

        4) 若是repl是個字符串,則其中的反斜杆會被處理過,好比 \n 會被轉成換行符,反斜杆加數字會被替換成相應的組,好比 \6 表示pattern匹配到的第6個組的內容

import re
test="Hi, nice to meet you where are you from?"
print(re.sub(r'\s','-',test))          # Hi,-nice-to-meet-you-where-are-you-from?
print(re.sub(r'\s','-',test,5))        # Hi,-nice-to-meet-you-where are you from?
print(re.sub('o','**',test))           # Hi, nice t** meet y**u where are y**u fr**m?
sub使用

    ⒍ escape(string)

        1)   re.escape(pattern) 能夠對字符串中全部可能被解釋爲正則運算符的字符進行轉義的應用函數。

        2)  若是字符串很長且包含不少特殊技字符,而你又不想輸入一大堆反斜槓,或者字符串來自於用戶(好比經過raw_input函數獲取輸入的內容),

                                    且要用做正則表達式的一部分的時候,能夠用這個函數

import re
print(re.escape('www.python.org'))
escape使用

  三、re模塊中的匹配對象和組 group()

      1)group方法返回模式中與給定組匹配的字符串,若是沒有給定匹配組號,默認爲組0

      2)m.group() == m.group(0) == 全部匹配的字符

import re
a = "123abc321efg456"
print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0))    # 123abc321
print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).groups())    # ('123', 'abc', '321')
print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1))    # 123
print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2))    # abc
print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3))    # 321


import re
m = re.match('(..).*(..)(..)','123456789')
print(m.group(0))              # 123456789
print(m.group(1))              # 12
print(m.group(2))              # 67
print(m.group(3))              # 89
group(0)與group(1)區別比較
import re
m = re.match('www\.(.*)\..*','www.baidu.com')
print(m.group(1))           # baidu
print(m.start(1))             # 4
print(m.end(1))             # 9
print(m.span(1))            # (4, 9)
group()匹配之返回匹配索引
import re
test = 'dsfdf 22 g2323  GigabitEthernet0/3        10.1.8.1        YES NVRAM up eee'
# print(re.match('(\w.*\d)\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+YES\s+NVRAM\s+(\w+)\s+(\w+)\s*', test).groups())

ret = re.search(  r'(\w*\/\d+).*\s(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*(\s+up\s+)',test ).groups()
print(ret)          # 運行結果: ('GigabitEthernet0/3', '10.1.8.1', ' up ')

#1. (\w*\d+\/\d+)      匹配結果爲:GigabitEthernet0/3
#1.1   \w*: 匹配全部字母數字     
#1.2   /\d+:匹配全部斜槓開頭後根數字 (好比:/3 )

#2. (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})  匹配結果爲:10.1.8.1

#3. \s+up\s+   匹配結果爲: up 這個單詞,先後都爲空格
group()匹配ip,狀態以元組返回

   四、re模塊其餘知識點

import re
#匹配時忽略大小寫
print(re.search("[a-z]+","abcdA").group())                #abcd
print(re.search("[a-z]+","abcdA",flags=re.I).group())            #abcdA
#連同換行符一塊兒匹配:
#'.'默認匹配除\n以外的任意一個字符,若指定flag DOTALL,則匹配任意字符,包括換行
print(re.search(r".+","\naaa\nbbb\nccc").group())            #aaa
print(re.search(r".+","\naaa\nbbb\nccc",flags=re.S))            
        #<_sre.SRE_Match object; span=(0, 12), match='\naaa\nbbb\nccc'>
print(re.search(r".+","\naaa\nbbb\nccc",flags=re.S).group())
                                                                                   aaa
                                                                                   bbb
                                                                                   ccc
                                                    
re匹配忽略大小寫,匹配換行
1)init_l=[i for i in re.split('(\-\d+\.*\d*)',expression) if i]
        a. 按照相似負數的字符串分割成列表
        b. \-\d+\.*\d*是爲了能夠匹配浮點數(好比:3.14)
        c. (if i)是爲了去除列表中的空元素
        d. 分割結果:['-1', '-2', '*((', '-60', '+30+(',
2)re.search('[\+\-\*\/\(]$',expression_l[-1])
        a. 匹配expression_l列表最後一個元素是 +,-,*,/,( 這五個符號就是負數
3)new_l=[i for i in re.split('([\+\-\*\/\(\)])',exp) if i]
        a. 將字符串按照+,-,*,/,(,)切分紅列表(不是正真的負數就切分)
4)print(re.split('([\+\-])','-1+2-3*(2*2+3)'))            #按照加號或者減號分割成列表
運行結果: ['', '-', '1', '+', '2', '-', '3*(2*2', '+', '3)']
計算器用到的幾個知識點

 1.15  xml處理模塊     返回頂部

   一、xml模塊的做用

      1.  xml是實現不一樣語言或程序之間進行數據交換的協議,跟json差很少

      2. 但json使用起來更簡單,不過,古時候,在json還沒誕生的黑暗年代,你們只能選擇用xml呀

      3. 至今不少傳統公司如金融行業的不少系統的接口還主要是xml

   二、手動建立xmltest.xml文件,並使用python讀取xml文件中的數據

<?xml version="1.0"?>                    <!--#版本號-->
<data>                                    <!--#data是一個標籤隨便寫,data中包含三組數據,每組數據都是country標籤-->
    <country name="Liechtenstein">    <!--#name是給country標籤取的名字-->
        <rank updated="yes">2</rank>    <!--#兩個</rank>中的2是數據排名,updated="yes"是屬性可隨便寫-->
        <year>2008</year>                <!--#在2008年-->
        <gdppc>141100</gdppc>            <!--#人均gdp是141100-->
        <neighbor name="Austria" direction="E"/>          <!--#他有個鄰居有兩個屬性 name 和 direction-->
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</data>
xmltest.xml文件內容
import xml.etree.ElementTree as ET

tree = ET.parse("xmltest.xml")  # 寫上要處理的文件明智
root = tree.getroot()
print(root)  # 打印的是內存地址信息
print(root.tag)  # root.tag = data其實就是標籤的名字

# 遍歷xml文檔
for child in root:  # 循環每一個子標籤中的內容 其中root是一個內存對象,在這裏是全部的文件對象
    print(child.tag, child.attrib)  # 1 child.tag其實就是data數據中的標籤名在這裏都是country
    for i in child:  # 2  child.attrib其實就是data數據中的屬性
        # 3 好比:屬性 {'name': 'Liechtenstein'}  {'name': 'Singapore'}
        print(i.tag, i.text, i.attrib)  # 1 好比在數據中 <rank updated="yes">2</rank>
    # 2 打印的結果就是 rank 2 {'updated': 'yes'}
    # 3 其中 i.tag = rank  表示內層標籤名
    # 4  i.text = 2  表示這個標籤的數據
    # 5 i.attrib = {'updated': 'yes'} 表示標籤屬性
# 只遍歷year 節點
for node in root.iter('year'):
    print(node.tag, node.text)
建立python文件讀取xmltest.xml內容
#一、運行第一個for循環的結果
<Element 'data' at 0x00A3A510>
data
country {'name': 'Liechtenstein'}


rank 2 {'updated': 'yes'}
year 2008 {}
gdppc 141100 {}
neighbor None {'name': 'Austria', 'direction': 'E'}
neighbor None {'name': 'Switzerland', 'direction': 'W'}
country {'name': 'Singapore'}
rank 5 {'updated': 'yes'}
year 2011 {}
gdppc 59900 {}
neighbor None {'name': 'Malaysia', 'direction': 'N'}
country {'name': 'Panama'}
rank 69 {'updated': 'yes'}
year 2011 {}
gdppc 13600 {}
neighbor None {'name': 'Costa Rica', 'direction': 'W'}
neighbor None {'name': 'Colombia', 'direction': 'E'}


#二、 運行第二個for循環的結果
year 2008
year 2011
year 2011


下面以xmltest.xml中一組數據爲例解釋:
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>

#三、第一個for循環各項的意義:
root.tag = data
child.tag = country
child.attrib = {'name': 'Liechtenstein'}
i.tag = rank, year, gdppc, neighbor, neighbor
i.text = 2, 2008,141100, None, None
i.attrib = {'updated': 'yes'}, {}, {}
{'direction': 'E', 'name': 'Austria'}
{'direction': 'W', 'name': 'Switzerland'}
#四、第二個for循環各項的意義
node.tag = year      #標籤
node.text = 2008       #數據
對python讀取xml文件解釋

  三、python修改和刪除xmltest.xml文檔內容

import xml.etree.ElementTree as ET

tree = ET.parse("xmltest.xml")
root = tree.getroot()

#修改
for node in root.iter('year'):        #循環data中三組數據,找到標籤名爲year的內容
    new_year = int(node.text) + 1        # node.text表示year標籤中的數據部分 將其加1
    node.text = str(new_year)        # 從新賦值node.text 即給year種數據部分賦值
    node.set("updated","yes")        #而且在year標籤的字段中添加新屬性:year updated="yes
tree.write("xmltest.xml")
'''
#一、這裏僅取出data中的一組數據:
<country name="Liechtenstein">
    <rank updated="yes">2</rank>
    <year>2008</year>
    <gdppc>141100</gdppc>
    <neighbor name="Austria" direction="E"/>
    <neighbor name="Switzerland" direction="W"/>
</country>
'''

'''
#二、這裏是修改後的數據:
<country name="Liechtenstein">
    <rank updated="yes">2</rank>
    <year updated="yes">2009</year>
    <gdppc>141100</gdppc>
    <neighbor direction="E" name="Austria" />
    <neighbor direction="W" name="Switzerland" />
</country>
'''
python修改xml文件
import xml.etree.ElementTree as ET                    

tree = ET.parse("xmltest.xml")
root = tree.getroot()

#刪除node
for country in root.findall('country'):        #在文件中尋找全部標籤名爲'country'的全部組數據
   rank = int(country.find('rank').text)        #在'country'數據組中找出全部標籤名爲'rank'中的數據
   if rank > 50:                    #若是這個數據大於50
     root.remove(country)                #將這個'country'數據組從xml文件中刪除

tree.write('output.xml')

注:執行結束後發現原來的xml文件的data數據中有三組'country'數據,如今只有兩組了
刪除指定xml文檔

  四、使用python建立xml文檔

import xml.etree.ElementTree as ET

new_xml = ET.Element("personinfolist")           #personinfolist表示根節點

#1 根節點"personinfolist"的第一個子節點"personinfo"
personinfo = ET.SubElement(new_xml,"personinfo",attrib={"enrolled":"yes"})
        #指定在new_xml根節點中建立子節點名字爲"personinfo" 屬性爲  enrolled="yes"
name = ET.SubElement(personinfo,"name")    #在personinfo子節點中建立一個子節點標籤是"name"
name.text = 'Alex Li'            #給剛剛建立的name標籤加入一個數據 'Alex Li'
age = ET.SubElement(personinfo,"age",attrib={"checked":"no"})
age.text = '33'    #在personinfo子節點中建立一個子節點標籤是age 屬性是 checked":"no"

#2 根節點"personinfolist"的第一個子節點"personinfo2"
personinfo2 = ET.SubElement(new_xml,"personinfo",attrib={"enrolled":"no"})
name = ET.SubElement(personinfo2,"name")
name.text = 'Oldboy Ran'
age = ET.SubElement(personinfo2,"age")
age.text = '19'

et = ET.ElementTree(new_xml) #生成文檔對象
et.write("test.xml", encoding="utf-8",xml_declaration=True)

ET.dump(new_xml) #打印生成的格式

#一、說明
"test.xml" : 生成的文檔名稱
encoding="utf-8" : 指定字符編碼
xml_declaration=True :指定文檔格式是xml

#二、運行結果
<?xml version='1.0' encoding='utf-8'?>
<personinfolist>
    <personinfo enrolled="yes">
        <name>Alex Li</name>
        <age checked="no">33</age>
    </personinfo>

    <personinfo enrolled="no">
        <name>Oldboy Ran</name>
        <age>19</age>
    </personinfo>
</personinfolist>
使用python建立xml文檔

 1.16  PyYAML模塊     返回頂部

  1. 安裝PyYAML

      1)Download the source package PyYAML-3.08.tar.gz and unpack it.

      2)Go to the directory PyYAML-3.08 and run 

      3)PyYAML下載網址 http://pyyaml.org/wiki/PyYAML

                  $ python setup.py install

  2. 安裝LibYAML

      1)If you want to use LibYAML bindings, which are much faster than the pure Python version,

      2)you need to download and install LibYAML.

      3)Then you may build and install the bindings by executing.

         $ python setup.py --with-libyaml install

  3. 使用的一個小例子

import yaml
document = """
  a: 1
  b:
    c: 3
    d: 4
"""
print(yaml.dump(yaml.load(document)))
'''#一、將YAML格式文件轉換成python格式文件
a: 1
b: {c: 3, d: 4}
'''


print(yaml.dump(yaml.load(document), default_flow_style=False))
'''#二、將python格式文件轉換成YAML格式文件
a: 1
b:
  c: 3 
  d: 4
'''
YAML使用舉例

1.17 ConfigParser模塊     返回頂部

     做用: 用於生成和修改常見配置文檔,當前模塊的名稱在 python 3.x 版本中變動爲 configparser。

   一、來看一個好多軟件的常見文檔格式以下

[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes

[bitbucket.org]
User = hg

[topsecret.server.com]
Port = 50022
ForwardX11 = no


#一、文件中內容包含三個節點:和python中字典效果同樣
'''
[DEFAULT]
[bitbucket.org]
[topsecret.server.com]
'''
好多軟件的常見文檔格式事例

  二、用python生成一個這樣的文檔

import configparser

config = configparser.ConfigParser()         #生成一個configparser處理的對象賦值爲config

#1 建立第一個節點"DEFAULT"
config["DEFAULT"] = {'ServerAliveInterval': '45',
                      'Compression': 'yes',
                     'CompressionLevel': '9'}

#2 建立第二個節點'bitbucket.org'
config['bitbucket.org'] = {}
config['bitbucket.org']['User'] = 'hg'

#3 建立第三個節點'topsecret.server.com'
config['topsecret.server.com'] = {}
config['topsecret.server.com']['Host Port'] = '50022'     # mutates the parser
config['topsecret.server.com']['ForwardX11'] = 'no'  # same here

config['DEFAULT']['ForwardX11'] = 'yes'            #在"DEFAULT"中添加一個內容

with open('example.ini', 'w') as configfile:        #將生成的內容寫入'example.ini'文件中
   config.write(configfile)
用python生成一個這樣的文檔
import configparser

config = configparser.ConfigParser()
config.read('example.ini')


#1 這裏打印的是全部的節點,可是"DEFAULT"節點是不會打印出來
print(config.sections())
# 運行結果: ['bitbucket.org', 'topsecret.server.com']

#2 這裏打印的是"DEFAULT"節點中的全部內容,變成一個字典打印出來
print(config.defaults())
# 運行結果:OrderedDict([('compressionlevel', '9'), ('serveraliveinterval', '45'), ('compression', 'yes'), ('forwardx11', 'yes')])

#3 打印出具體節點中的某一項內容
print(config['bitbucket.org']['user'])
# 運行結果: hg

#4 遍歷指定節點中的全部key值,若是在default模塊有單本身模塊沒有的也會打印出來
for key in config["topsecret.server.com"]: print(key)
'''
運行結果:
host port
forwardx11
compressionlevel
serveraliveinterval
compression
'''

#5 刪除example.ini文件中'bitbucket.org'節點中的全部內容
sec = config.remove_section('bitbucket.org')
# config.write(open('example.cfg', "w"))    #這裏是不修改原文件將內容寫到新文件中
config.write(open('example.ini', "w"))        #這裏是將改變的文件寫入原文件中
用python讀取剛剛生成的文檔
相關文章
相關標籤/搜索