Python自動化運維之九、模塊之sys、os、hashlib、random、time&datetime、logging、subprocess

python模塊

  用一砣代碼實現了某個功能的代碼集合。 相似於函數式編程和麪向過程編程,函數式編程則完成一個功能,其餘代碼用來調用便可,提供了代碼的重用性和代碼間的耦合。而對於一個複雜的功能來,可能須要多個函數才能完成(函數又能夠在不一樣的.py文件中),n個 .py 文件組成的代碼集合就稱爲模塊。模塊分爲內建模塊、自定義的模塊、安裝的第三方的模塊html

導入模塊

Python之因此應用愈來愈普遍,在必定程度上也依賴於其爲程序員提供了大量的模塊以供使用,若是想要使用模塊,則須要導入。導入模塊有一下幾種方法:python

import module
from module.xx.xx import xx
from module.xx.xx import xx as rename 
from module.xx.xx import *

導入模塊其實就是告訴Python解釋器去解釋那個py文件linux

  • 導入一個py文件,解釋器解釋該py文件
  • 導入一個包,解釋器解釋該包下的 __init__.py 文件

那麼問題來了,導入模塊時是根據那個路徑做爲基準來進行的呢?即:sys.path程序員

>>> import sys
>>> print(sys.path)
['', '/home/tomcat/.pyenv/versions/3.5.1/lib/python35.zip', 
'/home/tomcat/.pyenv/versions/3.5.1/lib/python3.5', 
'/home/tomcat/.pyenv/versions/3.5.1/lib/python3.5/plat-linux', 
'/home/tomcat/.pyenv/versions/3.5.1/lib/python3.5/lib-dynload', 
'/home/tomcat/.pyenv/versions/3.5.1/lib/python3.5/site-packages']

若是sys.path路徑列表沒有你想要的路徑,能夠經過 sys.path.append('路徑') 添加。算法

import sys
import os
project_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(project_path) 

經常使用內置模塊

內置模塊是Python自帶的功能,在使用內置模塊相應的功能時,須要【先導入】再【使用】shell

1、sys

用於提供對Python解釋器相關的操做:編程

sys.argv           命令行參數List,第一個元素是程序自己路徑
sys.exit(n)        退出程序,正常退出時exit(0)
sys.version        獲取Python解釋程序的版本信息
sys.maxint         最大的Int值
sys.path           返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值
sys.platform       返回操做系統平臺名稱
sys.stdin          輸入相關
sys.stdout         輸出相關
sys.stderror       錯誤相關

進度條示例:  windows

import sys
import time def view_bar(num,total): rate = num / total rate_num = int(rate * 100) r = '\r%s%d%%' % (">"*num,rate_num) sys.stdout.write(r) sys.stdout.flush() if __name__ == '__main__': for i in range(0, 100): time.sleep(0.1) view_bar(i, 100)

2、os

用於提供系統級別的操做:python3.x

os.getcwd()                 獲取當前工做目錄,即當前python腳本工做的目錄路徑
os.chdir("dirname")         改變當前腳本工做目錄;至關於shell下cd
os.curdir                   返回當前目錄: ('.')
os.pardir                   獲取當前目錄的父目錄字符串名:('..')
os.makedirs('dir1/dir2')    可生成多層遞歸目錄
os.removedirs('dirname1')   若目錄爲空,則刪除,並遞歸到上一級目錄,如若也爲空,則刪除,依此類推
os.mkdir('dirname')         生成單級目錄;至關於shell中mkdir dirname
os.rmdir('dirname')         刪除單級空目錄,若目錄不爲空則沒法刪除,報錯;至關於shell中rmdir dirname
os.listdir('dirname')       列出指定目錄下的全部文件和子目錄,包括隱藏文件,並以列表方式打印
os.remove()                 刪除一個文件
os.rename("oldname","new")  重命名文件/目錄
os.stat('path/filename')    獲取文件/目錄信息
os.sep                      操做系統特定的路徑分隔符,win下爲"\\",Linux下爲"/"
os.linesep                  當前平臺使用的行終止符,win下爲"\t\n",Linux下爲"\n"
os.pathsep                  用於分割文件路徑的字符串
os.name                     字符串指示當前使用平臺。win->'nt'; Linux->'posix'
os.system("bash command")   運行shell命令,直接顯示,不能保存執行結果
os.popen("bash command").read() 運行shell命令,能夠保存執行結果 os.environ 獲取系統環境變量 os.path.abspath(path) 返回path規範化的絕對路徑 os.path.split(path) 將path分割成目錄和文件名二元組返回 os.path.dirname(path) 返回path的目錄。其實就是os.path.split(path)的第一個元素 os.path.basename(path) 返回path最後的文件名。如何path以/或\結尾,那麼就會返回空值。即os.path.split(path)的第二個元素 os.path.exists(path) 若是path存在,返回True;若是path不存在,返回False os.path.isabs(path) 若是path是絕對路徑,返回True os.path.isfile(path) 若是path是一個存在的文件,返回True。不然返回False os.path.isdir(path) 若是path是一個存在的目錄,則返回True。不然返回False os.path.join(path1[, path2[, ...]]) 將多個路徑組合後返回,第一個絕對路徑以前的參數將被忽略 os.path.getatime(path) 返回path所指向的文件或者目錄的最後存取時間 os.path.getmtime(path) 返回path所指向的文件或者目錄的最後修改時間

3、hashlib

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

import hashlib
 
# ######## md5 ########
hash = hashlib.md5()
# help(hash.update)
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())
print(hash.digest())
 
 
######## sha1 ########
 
hash = hashlib.sha1()
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())
 
# ######## sha256 ########
 
hash = hashlib.sha256()
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())
 
 
# ######## sha384 ########
 
hash = hashlib.sha384()
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())
 
# ######## sha512 ########
 
hash = hashlib.sha512()
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())

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

import hashlib
 
# ######## md5 ########
 
hash = hashlib.md5(bytes('898oaFs09f',encoding="utf-8"))
hash.update(bytes('admin',encoding="utf-8"))
print(hash.hexdigest())

4、random

import random
 
print(random.random())              # 生成0-1之間的隨機小數
print(random.randint(1, 20))       #生成1到20的整數包括20
print random.uniform(10, 20)     #生成10到20之間的浮點數
print(random.randrange(1, 10))  #生成1到10的證書不包括10,第3個參數能夠指定步長
print(random.choice(["JGood", "is", "a", "handsome", "boy"])) # 從序列中隨機選一個數

# 每次對序列隨機排序
p = ["Python", "is", "powerful", "simple"]
random.shuffle(p)
print(p)

隨機驗證碼

import random

li = [] for i in range(6): r = random.randint(0, 4) if r == 2 or r == 4: num = random.randrange(0, 10) li.append(str(num)) else: temp = random.randrange(65,91) c = chr(temp) li.append(c) result = "".join(li) print(result)
一些例子

5、time&datetime

時間相關的操做,時間有三種表示方式:

  • 時間戳                1970年1月1日以後的秒,即:time.time()
  • 格式化的字符串    2014-11-11 11:11,    即:time.strftime('%Y-%m-%d')
  • 結構化時間          元組包含了:年、日、星期等... time.struct_time    即:time.localtime()

time

import time

print(time.clock())    #返回處理器時間,3.3開始已廢棄
print(time.process_time()) #返回處理器時間,3.3開始已廢棄
print(time.time()) #返回當前系統時間戳輸出:1471161757.5214906 print(time.ctime()) #輸出字符串格式時間:Sun Aug 14 16:04:02 2016 ,當前系統時間 print(time.ctime(time.time()-86640)) #將時間戳轉爲字符串格式
print(time.gmtime()) #獲取結構化時間 print(time.gmtime(time.time()-86640)) #將時間戳轉換成struct_time格式 print(time.localtime(time.time()-86640)) #將時間戳轉換成struct_time格式,但返回的本地時間 print(time.mktime(time.localtime())) #與time.localtime()功能相反,將struct_time格式轉回成時間戳格式 time.sleep(4) #睡上4秒 print(time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime()) ) #將struct_time格式轉成指定的字符串格式 print(time.strptime("2016-01-28","%Y-%m-%d") ) #將字符串格式轉換成struct_time格式

datetime

import datetime

print(datetime.date.today()) #輸出格式 2016-01-26
print(datetime.date.fromtimestamp(time.time()-864400) )  #2016-01-16 將時間戳轉成日期格式
current_time = datetime.datetime.now() #
print(current_time)   #輸出2016-01-26 19:04:30.335935
print(current_time.timetuple())  #返回struct_time格式
 
#datetime.replace([year[, month[, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]]]]])
print(current_time.replace(2014,9,12))  #輸出2014-09-12 19:06:24.074900,返回當前時間,但指定的值將被替換
 
str_to_date = datetime.datetime.strptime("21/11/06 16:30", "%d/%m/%y %H:%M") #將字符串轉換成日期格式
new_date = datetime.datetime.now() + datetime.timedelta(days=10) #比如今加10天
new_date = datetime.datetime.now() + datetime.timedelta(days=-10) #比如今減10天
new_date = datetime.datetime.now() + datetime.timedelta(hours=-10) #比如今減10小時
new_date = datetime.datetime.now() + datetime.timedelta(seconds=120) #比如今+120s
print(new_date)
View Code

6、logging模塊  

不少程序都有記錄日誌的需求,而且日誌中包含的信息即有正常的程序訪問日誌,還可能有錯誤、警告等信息輸出,python的logging模塊提供了標準的日誌接口,你能夠經過它存儲各類格式的日誌,logging的日誌能夠分爲 debug()info()warning()error() and critical() 5個級別,下面咱們看一下怎麼用。

日誌級別對應的數字:

CRITICAL = 50   ERROR = 40   WARNING = 30   INFO = 20   DEBUG = 10   NOTSET = 0

日誌記錄格式:

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

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S %p',
                    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將沒法完成,須要自定義文件和日誌操做對象。

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

import logging

#獲取日誌器對象
logger = logging.getLogger('TEST-LOG')  # 返回一個logger對象,沒有指定的話默認是root logger
logger.setLevel(logging.DEBUG)  #設置全局日誌級別

#定義屏幕控制器把日誌輸出屏幕
ch = logging.StreamHandler()   
ch.setLevel(logging.DEBUG)   # 輸出屏幕的日誌級別
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)   # 給輸出屏幕的日誌設置日誌格式
logger.addHandler(ch)        # 將設定好的控制器添加到日誌器中

#定義文件控制器把日誌輸出文件
fh = logging.FileHandler("access.log")  
fh.setLevel(logging.WARNING)  #設置輸出文件的日誌級別
formatter1 = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter1)   # 給輸出文件的日誌設置日誌格式
logger.addHandler(fh)         # 將設定好的控制器添加到日誌器中

logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')

注意:局部日誌級別只有大於全局日誌級別纔會記錄  

7、subprocess模塊   

能夠執行shell命令的相關模塊和函數有:

  • os.system()   直接使用shell命令,不能保存運行的結果
  • os.spawn*    
  • os.popen().read()  直接使用shell命令,能夠保存運行的結果
  • commands.*  python3.x已經廢除
  • subprocess

一、os.system()

>>> import os
>>> os.system('ls')
a.py   b.py   Desktop  myenv35	PycharmProjects  workplace
a.txt  b.txt  myenv27  pass.py	scripts
0

二、os.popen().read()  

>>> import os
>>> fi = os.popen('ls').read()
>>> print(fi)
a.py
a.txt
b.py
b.txt

三、commands(在python2.x中執行)

>>> import commands
>>> result = commands.getoutput('ls')
>>> print(result)
a.py
a.txt
b.py
b.txt

>>> result1 = commands.getstatusoutput('ls')
>>> print(result1)
(0, 'a.py\na.txt\nb.py\nb.txt\nDesktop\nmyenv27\nmyenv35\npass.py\nPycharmProjects\nscripts\nworkplace')

四、subprocess  

subprocess.call()  執行命令,返回狀態碼,shell=False,第一個參數必須是列表,shell=True,第一個參數就直接輸入命令便可

>>> ret = subprocess.call(["ls", "-l"], shell=False)
或: >>> ret = subprocess.call("ls -l", shell=True)

subprocess.check_call() 執行命令,若是執行狀態碼是 0 ,則返回0,不然拋異常

>>> ret = subprocess.check_call(["ls", "-l"],shell=False)
>>> print(ret) >>> ret = subprocess.check_call("exit 1", shell=True)
>>> print(ret)

subprocess.check_output() 執行命令,若是狀態碼是 0 ,則返回執行結果,不然拋異常,注意這裏返回的是字節類型,須要轉換

>>> ret = subprocess.check_output(["echo", "Hello World!"],shell=False)
>>> print(str(ret,encoding='utf-8'))
或 >>> ret = subprocess.check_output("exit 1", shell=True)
>>> print(str(ret,encoding='utf-8'))

subprocess.run()  python3.5新加的功能,代替os.system,os.spawn

>>> import subprocess

>>> subprocess.run(["ls", "-l"])
total 56
-rw-rw-r-- 1 tomcat tomcat    61  8月 11 23:27 a.py
-rw-rw-r-- 1 tomcat tomcat 12929  8月  8 18:03 a.txt
CompletedProcess(args=['ls', '-l'], returncode=0)

>>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0, stdout=b'crw-rw-rw- 1 root root 1, 3  8\xe6\x9c\x88 11 09:27 /dev/null\n')

subprocess.Popen()  用於執行復雜的系統命令,是上面方法的底層實現

調用subprocess.run(...)是推薦的經常使用方法,在大多數狀況下能知足需求,但若是你可能須要進行一些複雜的與系統的交互的話,你還能夠用subprocess.Popen(),語法以下:

p = subprocess.Popen("find ~/ -size +1000 -exec ls -shl {} \;",shell=True,stdout=subprocess.PIPE)
print(p.stdout.read())

參數:

  • args:shell命令,能夠是字符串或者序列類型(如:list,元組)
  • bufsize:指定緩衝。0 無緩衝,1 行緩衝,其餘 緩衝區大小,負值 系統緩衝
  • stdin, stdout, stderr:分別表示程序的標準輸入、輸出、錯誤句柄
  • preexec_fn:只在Unix平臺下有效,用於指定一個可執行對象(callable object),它將在子進程運行以前被調用
  • close_sfs:在windows平臺下,若是close_fds被設置爲True,則新建立的子進程將不會繼承父進程的輸入、輸出、錯誤管道。
  • 因此不能將close_fds設置爲True同時重定向子進程的標準輸入、輸出與錯誤(stdin, stdout, stderr)。
  • shell:同上
  • cwd:用於設置子進程的當前目錄,至關於shell中cd進入當前目錄
  • env:用於指定子進程的環境變量。若是env = None,子進程的環境變量將從父進程中繼承。
  • universal_newlines:不一樣系統的換行符不一樣,True -> 贊成使用 \n
  • startupinfo與createionflags只在windows下有效
  • 將被傳遞給底層的CreateProcess()函數,用於設置子進程的一些屬性,如:主窗口的外觀,進程的優先級等等

終端輸入的命令分爲兩種:

  • 輸入便可獲得輸出,如:ifconfig
  • 輸入進行某環境,依賴再輸入,如:python

(1)輸入便可獲得輸出  

import subprocess

obj = subprocess.Popen(["mkdir","test"],cwd='/tmp/',)
或者
obj1 = subprocess.Popen("mkdir test1", shell=True, cwd='/tmp/',)

(2)輸入進行某環境,依賴再輸入,經過輸入,輸出,錯誤管道,輸入數據,獲取數據

import subprocess

obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
obj.stdin.write("print(1)\n")
obj.stdin.write("print(2)")
obj.stdin.close()

cmd_out = obj.stdout.read()
obj.stdout.close()
cmd_error = obj.stderr.read()
obj.stderr.close()

print(cmd_out)
print(cmd_error)

或者
obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
obj.stdin.write("print(1)\n")
obj.stdin.write("print(2)")

out_error_list = obj.communicate()
print(out_error_list)

或者
obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)

out_error_list = obj.communicate('print("hello")')
print(out_error_list)
相關文章
相關標籤/搜索