天天看點

Python高手之路【七】python基礎之子產品

本節大綱

  1. 子產品介紹
  2. time &datetime子產品
  3. random
  4. os
  5. sys
  6. shutil
  7. json & picle
  8. shelve
  9. xml處理
  10. yaml處理
  11. configparser
  12. hashlib
  13. subprocess
  14. logging子產品
  15. re正規表達式

1:子產品介紹

子產品,用一砣代碼實作了某個功能的代碼集合。 

類似于函數式程式設計和面向過程程式設計,函數式程式設計則完成一個功能,其他代碼用來調用即可,提供了代碼的重用性和代碼間的耦合。而對于一個複雜的功能來,可能需要多個函數才能完成(函數又可以在不同的.py檔案中),n個 .py 檔案組成的代碼集合就稱為子產品。

如:os 是系統相關的子產品;file是檔案操作相關的子產品

子產品分為三種:

  • 自定義子產品
  • 内置标準子產品(又稱标準庫)
  • 開源子產品

子產品導入的三種方式:

方法一:

import modname       

用import語句導入子產品,就在目前的名稱空間(namespace)建立了一個到該子產品的引用.這種引用必須使用全稱,也就是說,當使用在被導入子產品中定義的函數時,必須包含子產品的名字。是以不能隻使用 funcname,而應該使用 modname.funcname

方法二:

from modname import funcname   
from modname import fa, fb, fc 
from modname import *       

        與第1種方法的差別:funcname 被直接導入到本地名字空間去了,是以它可以直接使用,而不需要加上子產品名的限定* 表示,該子產品的所有公共對象(public objects)都被導入到 目前的名稱空間,也就是任何隻要不是以”_”開始的東西都會被導入。 

       modname沒有被定義,是以modname.funcname這種方式不起作用。并且,如果funcname如果已經被定義,它會被新版本(該導入子產品中的版本)所替代。如果funcname被改成指向其他對象,modname不能不會覺察到。 

建議:

  1. 如果你要經常通路子產品的屬性和方法,且不想一遍又一遍地敲入子產品名,使用 from module import 
  2. 如果你想要有選擇地導入某些屬性和方法,而不想要其它的,使用 from module import 
  3. 如果子產品包含的屬性和方法與你的某個子產品同名,你必須使用import module來避免名字沖突 
  4. 盡量少用 from module import * ,因為判定一個特殊的函數或屬性是從哪來的有些困難,并且會造成調試和重構都更困難。

2:time & datetime子產品

1 #_*_coding:utf-8_*_
 2 __author__ = 'Alex Li'
 3 
 4 import time
 5 
 6 
 7 # print(time.clock()) #傳回處理器時間,3.3開始已廢棄 , 改成了time.process_time()測量處理器運算時間,不包括sleep時間,不穩定,mac上測不出來
 8 # print(time.altzone)  #傳回與utc時間的時間差,以秒計算\
 9 # print(time.asctime()) #傳回時間格式"Fri Aug 19 11:14:16 2016",
10 # print(time.localtime()) #傳回本地時間 的struct time對象格式
11 # print(time.gmtime(time.time()-800000)) #傳回utc時間的struc時間對象格式
12 
13 # print(time.asctime(time.localtime())) #傳回時間格式"Fri Aug 19 11:14:16 2016",
14 #print(time.ctime()) #傳回Fri Aug 19 12:38:29 2016 格式, 同上
15 
16 
17 
18 # 日期字元串 轉成  時間戳
19 # string_2_struct = time.strptime("2016/05/22","%Y/%m/%d") #将 日期字元串 轉成 struct時間對象格式
20 # print(string_2_struct)
21 # #
22 # struct_2_stamp = time.mktime(string_2_struct) #将struct時間對象轉成時間戳
23 # print(struct_2_stamp)
24 
25 
26 
27 #将時間戳轉為字元串格式
28 # print(time.gmtime(time.time()-86640)) #将utc時間戳轉換成struct_time格式
29 # print(time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime()) ) #将utc struct_time格式轉成指定的字元串格式
30 
31 
32 
33 
34 
35 #時間加減
36 import datetime
37 
38 # print(datetime.datetime.now()) #傳回 2016-08-19 12:47:03.941925
39 #print(datetime.date.fromtimestamp(time.time()) )  # 時間戳直接轉成日期格式 2016-08-19
40 # print(datetime.datetime.now() )
41 # print(datetime.datetime.now() + datetime.timedelta(3)) #目前時間+3天
42 # print(datetime.datetime.now() + datetime.timedelta(-3)) #目前時間-3天
43 # print(datetime.datetime.now() + datetime.timedelta(hours=3)) #目前時間+3小時
44 # print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #目前時間+30分
45 
46 
47 #
48 # c_time  = datetime.datetime.now()
49 # print(c_time.replace(minute=3,hour=2)) #時間替換      

3:random

import random
 
print(random.random())
print(random.randint(1, 2))
print(random.randrange(1, 10))      

4:OS子產品

用于提供系統級别的操作:

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.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所指向的檔案或者目錄的最後修改時間      

5:sys子產品

sys子產品用于提供對python解釋器相關的操作:

1 sys.argv           指令行參數List,第一個元素是程式本身路徑
2 sys.exit(n)        退出程式,正常退出時exit(0)
3 sys.version        擷取Python解釋程式的版本資訊
4 sys.maxint         最大的Int值
5 sys.path           傳回子產品的搜尋路徑,初始化時使用PYTHONPATH環境變量的值
6 sys.platform       傳回作業系統平台名稱
7 sys.stdout.write('please:')
8 val = sys.stdin.readline()[:-1]      

練習題:

1:讀寫使用者的輸入,根據使用者輸入,建立一個相應的目錄

import sys,os
print(sys.argv)
os.mkdir(sys.argv[1])      

在指令行下執行:

D:\Python\Python35-32>python e:/wwwroot/py
['e:/wwwroot/python/index.py', 'testdir']      

執行完畢,在D:\Python\Python35-32目錄下就多了一個testdir的目錄

2:自己寫一個簡單的腳本,可以在任何路徑導入

3:進度條,帶百分比

1 import sys,time
2 for i in range(31):
3     sys.stdout.write('\r')
4     sys.stdout.write("%s%% |%s" % (int(i/30*100),int(i/30*100)*'*'))
5     sys.stdout.flush()
6     time.sleep(0.1)      

 如何添加sys.path路徑:

import sys
sys.path.append("D:")#這裡寫需要添加的路徑
for i in sys.path:
    print(i)      

6:shuntil

進階的 檔案、檔案夾、壓縮包 處理子產品

shutil.copyfileobj(fsrc, fdst[, length]):将檔案内容拷貝到另一個檔案中

1 import shutil
2  
3 shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))      

shutil.copyfile(src, dst):拷貝檔案

shutil.copyfile('f1.log', 'f2.log')      

shutil.copymode(src, dst):僅拷貝權限。内容、組、使用者均不變

shutil.copymode('f1.log', 'f2.log')      

shutil.copystat(src, dst):僅拷貝狀态的資訊,包括:mode bits, atime, mtime, flags

shutil.copystat('f1.log', 'f2.log')      

shutil.copy(src, dst):拷貝檔案和權限

import shutil
 
shutil.copy('f1.log', 'f2.log')      

shutil.copy2(src, dst):拷貝檔案和狀态資訊

import shutil
 
shutil.copy2('f1.log', 'f2.log')      

shutil.ignore_patterns(*patterns)

shutil.copytree(src, dst, symlinks=False, ignore=None)

遞歸的去拷貝檔案夾

import shutil
 
shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))      
import shutil

shutil.copytree('f1', 'f2', symlinks=True, ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))      

shutil.rmtree(path[, ignore_errors[, onerror]])

遞歸的去删除檔案

import shutil
 
shutil.rmtree('folder1')      

shutil.move(src, dst)

遞歸的去移動檔案,它類似mv指令,其實就是重命名。

import shutil
 
shutil.move('folder1', 'folder3')      

shutil.make_archive(base_name, format,...)

建立壓縮包并傳回檔案路徑,例如:zip、tar

  • base_name: 壓縮包的檔案名,也可以是壓縮包的路徑。隻是檔案名時,則儲存至目前目錄,否則儲存至指定路徑,
  • 如:www =>儲存至目前路徑
  • 如:/Users/wupeiqi/www =>儲存至/Users/wupeiqi/
  • format: 壓縮包種類,“zip”, “tar”, “bztar”,“gztar”
  • root_dir: 要壓縮的檔案夾路徑(預設目前目錄)
  • owner: 使用者,預設目前使用者
  • group: 組,預設目前組
  • logger: 用于記錄日志,通常是logging.Logger對象
1 #将 /Users/wupeiqi/Downloads/test 下的檔案打包放置目前程式目錄
2 import shutil
3 ret = shutil.make_archive("wwwwwwwwww", 'gztar', root_dir='/Users/wupeiqi/Downloads/test')
4   
5   
6 #将 /Users/wupeiqi/Downloads/test 下的檔案打包放置 /Users/wupeiqi/目錄
7 import shutil
8 ret = shutil.make_archive("/Users/wupeiqi/wwwwwwwwww", 'gztar', root_dir='/Users/wupeiqi/Downloads/test')      

shutil 對壓縮包的處理是調用 ZipFile 和 TarFile 兩個子產品來進行的,詳細:

Python高手之路【七】python基礎之子產品
Python高手之路【七】python基礎之子產品
1 import zipfile
 2 
 3 # 壓縮
 4 z = zipfile.ZipFile('laxi.zip', 'w')
 5 z.write('a.log')
 6 z.write('data.data')
 7 z.close()
 8 
 9 # 解壓
10 z = zipfile.ZipFile('laxi.zip', 'r')
11 z.extractall()
12 z.close()
13 
14 zipfile解壓縮      

ZIPfile解壓縮

Python高手之路【七】python基礎之子產品
Python高手之路【七】python基礎之子產品
1 import tarfile
 2 
 3 # 壓縮
 4 tar = tarfile.open('your.tar','w')
 5 tar.add('/Users/wupeiqi/PycharmProjects/bbs2.log', arcname='bbs2.log')
 6 tar.add('/Users/wupeiqi/PycharmProjects/cmdb.log', arcname='cmdb.log')
 7 tar.close()
 8 
 9 # 解壓
10 tar = tarfile.open('your.tar','r')
11 tar.extractall()  # 可設定解壓位址
12 tar.close()
13 
14 tarfile解壓縮      

tarfile解壓縮

7:json & pickle 子產品

用于序列化的兩個子產品

  • json,用于字元串 和 python資料類型間進行轉換
  • pickle,用于python特有的類型 和 python的資料類型間進行轉換

Json子產品提供了四個功能:dumps、dump、loads、load

pickle子產品提供了四個功能:dumps、dump、loads、load

pickle子產品的dumps,loads示範:

假如現在有一個字典弄的資料,内容如下:

accounts = {
    1000:{
        'name':'poe',
        'password':'123456',
        'email':'[email protected]',
        'balance':15000,
        'phone':13888888888,
        'back_acc':{'ICBC':62202,'CBC':52202,'ABC':42202}
    },
    1001:{
        'name':'jet',
        'password':'654321',
        'email':'[email protected]',
        'balance':150,
        'phone':13888888888,
        'back_acc':{'ICBC':62202}
    }
}      

那麼如何将這個字典型的資料持久化儲存到硬碟裡呢?由于檔案的寫入隻允許儲存字元串,是以一般的方法無法将該字典型資料儲存到硬碟裡,這裡就需要用到pickle子產品的dumps與loads功能

Python高手之路【七】python基礎之子產品
Python高手之路【七】python基礎之子產品
1 import pickle
 2 accounts = {
 3     1000:{
 4         'name':'poe',
 5         'password':'123456',
 6         'email':'[email protected]',
 7         'balance':15000,
 8         'phone':13888888888,
 9         'back_acc':{'ICBC':62202,'CBC':52202,'ABC':42202}
10     },
11     1001:{
12         'name':'jet',
13         'password':'654321',
14         'email':'[email protected]',
15         'balance':150,
16         'phone':13888888888,
17         'back_acc':{'ICBC':62202}
18     }
19 }
20 f = open('account.db','wb')
21 f.write(pickle.dumps(accounts))
22 f.close()      

account.py

資料儲存後,那麼如果需要重寫,該怎麼辦呢?

Python高手之路【七】python基礎之子產品
Python高手之路【七】python基礎之子產品
1 import pickle
 2 acc_file_name = "account.db"
 3 account_file = open(acc_file_name,'rb')
 4 # print(pickle.loads(account_file.read()))
 5 account_dic = pickle.loads(account_file.read())
 6 account_file.close()
 7 account_dic[1000]['balance'] -= 500
 8 f = open(acc_file_name,'wb')
 9 f.write(pickle.dumps(account_dic))
10 f.close()
11 print(account_dic)      

shopping.py

驗證資料是否寫入成功:

Python高手之路【七】python基礎之子產品
Python高手之路【七】python基礎之子產品
import pickle
f = open("account.db",'rb')

account_db = pickle.loads(f.read())
print(account_db)      

check.py

1 import json
 2 s = '{"key1":"value1","key2":"value2"}'  # ==> 用json子產品将字元串轉化成其他資料類型,字元串裡出現引号必須用雙引号
 3 ret = json.loads(s)  # ==> loads 由字元串轉其他資料類型
 4 print(ret,type(ret))
 5 
 6 ret = json.load(open('ethan.txt','r')) # ==> 将文檔(内部是字元串格式)轉換成python的其他資料類型
 7 print(ret,type(ret))  # ==> 文檔裡是字典樣式的字元串
 8 
 9 l = '[11,22,3,56,75]'
10 result =json.loads(l)
11 print(result,type(result))
12 # 總結:
13 # json.loads()用于将形似字典、清單、元組的字元串,轉換成字典、清單、元組
14 # json.load() 用于将文檔(内容是形似字典、清單、元組的字元串)轉換成字典、清單、元組
15 
16 di = {"key1":"value1","key2":"value2"}
17 ret = json.dumps(di) # ==> 将字典、清單、元組 轉換成字元串格式
18 print(ret,type(ret))
19 
20 json.dump(di,open('ethan.txt','a+'))  # ==> 将字典、元組、清單轉換成字元串格式并寫入文檔
21 
22 import pickle
23 
24 d = {'name':'ethan','age':28}
25 ret = pickle.dumps(d) # ==> pickle将字典、元組、清單轉換成二進制
26 print(ret,type(ret))
27 
28 l = [11,22,3,45,54]
29 res = pickle.dumps(l)
30 print(res)
31 
32 pickle.dump(d,open('ethan.txt','ab')) # ==> 将字典、元組、清單轉換成二進制寫入文檔
33 
34 # 注意 dump load 不要一起運作,會報錯,一步一步來
35 
36 f = open('ethan.txt','rb')
37 r = pickle.loads(f.read()) # ==> 将二進制轉換成字典、清單、元組
38 print(r)      

11:configpaser子產品

configparser用于處理特定格式的檔案,其本質上是利用open來操作檔案。

Python高手之路【七】python基礎之子產品
Python高手之路【七】python基礎之子產品
1 # 注釋1
 2 ;  注釋2
 3  
 4 [section1] # 節點
 5 k1 = v1    # 值
 6 k2:v2       # 值
 7  
 8 [section2] # 節點
 9 k1 = v1    # 值
10 
11 指定格式      

指定格式

舉例:假如現在有一個ini的檔案,内容如下:

1 [poe]
2 age = 12
3 gender = 'female'
4 edu = 'daxue'
5 [jet]
6 age = 19
7 gender = 'male'      

1:利用configparser子產品提供的功能,擷取所有節點

import configparser
con = configparser.ConfigParser()#建立對象
#con對象的read功能,打開檔案讀取檔案,放進記憶體
con.read("ini",encoding="utf-8")
#con對象的sections,内在中尋找所有的[xxx]節點
result = con.sections()
print(result)
#con對象的options功能,擷取指定[xxx]節點下的内容
ret = con.options("poe")
print(ret)
##########################################
['poe', 'jet']
['age', 'gender', 'edu']      

2:擷取指定節點下所有的鍵值對

import configparser
con = configparser.ConfigParser()
con.read("ini",encoding="utf-8")

ret = con.items('poe')
print(ret)
##########################################
[('age', '12'), ('gender', "'female'"), ('edu', "'daxue'")]      

3:擷取指定節點下指定key的值

import configparser
con = configparser.ConfigParser()
con.read("ini",encoding="utf-8")

ret = con.get("poe","age")
print(ret)
##########################################
12      

4:檢查、删除、添加節點

1 import configparser
 2 con = configparser.ConfigParser()
 3 con.read("ini",encoding="utf-8")
 4 
 5 # 檢查節點是否存在,存在傳回True,否則傳回False
 6 has_sec = con.has_section("poe")
 7 print(has_sec)
 8 
 9 # 添加節點
10 con.add_section("andy")
11 con.write(open("ini","w"))
12 
13 # 删除節點
14 con.remove_section("trim")
15 con.write(open("ini","w"))      

5:檢查、删除、設定指定組内的鍵值對

1 import configparser
 2 con = configparser.ConfigParser()
 3 con.read("ini",encoding="utf-8")
 4 
 5 # 檢查andy節點下是否存在hobby鍵
 6 has_sec = con.has_option("andy","hobby")
 7 print(has_sec)
 8 
 9 # 删除
10 con.remove_option("andy","hobby")
11 con.write(open("ini","w"))
12 
13 # 設定
14 con.set("andy","from","beijing")
15 con.write(open("ini","w"))      

總結:

增:

  1. obj.add_section(塊節點名稱)   增加一個塊節點
  2. obj.set(塊節點名稱,鍵,值)         在指定的塊節點下增加鍵值

删:

  1. obj.remove_section(塊節點名稱)             删除指定塊節點(連同該塊節點下的所有鍵值都删除)
  2. obj.remove_option(塊節點名稱,該塊節點下的鍵名)             删除指定塊節點下指定鍵的鍵值對

改:

  1. obj.set(塊節點名稱,鍵,值) 

查:

  1. obj.sections()                 查詢所有的塊節點(且稱之為塊節點,如:上面檔案中的[poe],[jet]),傳回一個清單
  2. obj.options(塊節點名稱)              查詢指定塊節點下的所有鍵,傳回一個清單
  3. obj.items(塊節點名稱)                 查詢指定塊節點下的所有鍵及值,傳回一個清單(每個鍵值對儲存為一個元組)
  4. obj.get(塊節點名稱,塊節點下的鍵)                      查詢指定塊節點下,鍵所對就的值
  5. obj.has_section(塊節點名稱)                                查詢塊節點是否存在
  6. obj.has_option(塊節點名稱,塊節點下的鍵)        查詢指定塊節點下的鍵是否存在

12:hashlib

用于加密相關的操作,代替了md5子產品和sha子產品,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

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

python内置還有一個 hmac 子產品,它内部對我們建立 key 和 内容 進行進一步的處理然後再加密

import hmac
 
h = hmac.new(bytes('898oaFs09f',encoding="utf-8"))
h.update(bytes('admin',encoding="utf-8"))
print(h.hexdigest())      

 基于加密的登入程式:

Python高手之路【七】python基礎之子產品
Python高手之路【七】python基礎之子產品
import hashlib
def md5(arg) :
    p = hashlib.md5(bytes('admin',encoding='utf-8'))
    p.update(bytes(arg,encoding='utf-8'))
    return p.hexdigest()

def register(user,pwd) :
    with open("db","a",encoding="utf-8") as f :
        temp = user + "|" + md5(pwd)
        f.write(temp)
def login(user,pwd):
    with open('db','r',encoding="utf-8") as f :
        for line in f:
            u,p = line.strip().split("|")
            if u == user and p == md5(pwd):
                return True
    return False
i = input("1:login 2:register")
if i == '2':
    user = input('username : ')
    pwd = input('password : ')
    register(user,pwd)
elif i == '1':
    user = input('username :')
    pwd = input('password :')
    if login(user,pwd) :
        print('login success')
    else:
        print('login failed')      

使用者登入

 13:subprocess子產品

執行shell指令

call 

執行指令,傳回狀态碼

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

check_call

執行指令,如果執行狀态碼是 0 ,則傳回0,否則抛異常

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

check_output

執行指令,如果狀态碼是 0 ,則傳回執行結果,否則抛異常

subprocess.check_output(["echo", "Hello World!"])
subprocess.check_output("exit 1", shell=True)      

subprocess.Popen(...)

用于執行複雜的系統指令

參數:

  1. args:shell指令,可以是字元串或者序列類型(如:list,元組)
  2. bufsize:指定緩沖。0 無緩沖,1 行緩沖,其他 緩沖區大小,負值 系統緩沖
  3. stdin, stdout, stderr:分别表示程式的标準輸入、輸出、錯誤句柄
  4. preexec_fn:隻在Unix平台下有效,用于指定一個可執行對象(callable object),它将在子程序運作之前被調用
  5. close_sfs:在windows平台下,如果close_fds被設定為True,則新建立的子程序将不會繼承父程序的輸入、輸出、錯誤管道。
  6. 是以不能将close_fds設定為True同時重定向子程序的标準輸入、輸出與錯誤(stdin, stdout, stderr)。
  7. shell:同上
  8. cwd:用于設定子程序的目前目錄
  9. env:用于指定子程序的環境變量。如果env = None,子程序的環境變量将從父程序中繼承。
  10. universal_newlines:不同系統的換行符不同,True -> 同意使用 \n
  11. startupinfo與createionflags隻在windows下有效
  12. 将被傳遞給底層的CreateProcess()函數,用于設定子程序的一些屬性,如:主視窗的外觀,程序的優先級等等
import subprocess
ret1 = subprocess.Popen(["mkdir","t1"])
ret2 = subprocess.Popen("mkdir t2", shell=True)      

終端輸入的指令分為兩種:

  1. 輸入即可得到輸出,如:ifconfig
  2. 輸入進行某環境,依賴再輸入,如:python
import subprocess

obj = subprocess.Popen("mkdir t3", shell=True, cwd='/home/dev',)      
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)
      
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)")

out_error_list = obj.communicate()
print(out_error_list)
      
import subprocess

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)
      

 14:login子產品

用于便捷記錄日志且線程安全的子產品

1、單檔案日志

import logging
  
  
logging.basicConfig(filename='log.log',
                    format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S %p',
                    level=10)
  
logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.critical('critical')
logging.log(10,'log')
      

日志等級:

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

注:隻有【目前寫等級】大于【日志等級】時,日志檔案才被記錄。

日志記錄格式:

Python高手之路【七】python基礎之子產品

2、多檔案日志

對于上述記錄日志的功能,隻能将日志記錄在單檔案中,如果想要設定多個日志檔案,logging.basicConfig将無法完成,需要自定義檔案和日志操作對象。

# 定義檔案
file_1_1 = logging.FileHandler('l1_1.log', 'a', encoding='utf-8')
fmt = logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s")
file_1_1.setFormatter(fmt)

file_1_2 = logging.FileHandler('l1_2.log', 'a', encoding='utf-8')
fmt = logging.Formatter()
file_1_2.setFormatter(fmt)

# 定義日志
logger1 = logging.Logger('s1', level=logging.ERROR)
logger1.addHandler(file_1_1)
logger1.addHandler(file_1_2)


# 寫日志
logger1.critical('1111')
      
# 定義檔案
file_2_1 = logging.FileHandler('l2_1.log', 'a')
fmt = logging.Formatter()
file_2_1.setFormatter(fmt)

# 定義日志
logger2 = logging.Logger('s2', level=logging.INFO)
logger2.addHandler(file_2_1)
      

如上述建立的兩個日志對象

  • 當使用【logger1】寫日志時,會将相應的内容寫入 l1_1.log 和 l1_2.log 檔案中
  • 當使用【logger2】寫日志時,會将相應的内容寫入 l2_1.log 檔案中

繼續閱讀