模塊調用,datetime,time,logging,遞歸,雙層裝飾器, json,pickle迭代器和生成器

一.python模塊(導入,內置,自定義,開源)

1.模塊簡介html

模塊是一個包含全部你定義的函數和變量的文件,其後綴名是.py。模塊能夠被別的程序引入,以使用該模塊中的函數等功能。這也是使用python標準庫的方法。python

相似於函數式編程和麪向過程編程,函數式編程則完成一個功能,其餘代碼用來調用便可,提供了代碼的重用性和代碼間的耦合。而對於一個複雜的功能來,可能須要多個函數才能完成(函數又能夠在不一樣的.py文件中),n個 .py 文件組成的代碼集合就稱爲模塊。linux

2.模塊的引入算法

在Python中用關鍵字import來引入某個模塊,好比要引用模塊math,就能夠在文件最開始的地方用import math來引入。在調用math模塊中的函數時,必須這樣引用:shell

模塊名.函數名
例:
import sys
import module

 

有時候咱們只須要用到模塊中的某個函數,只須要引入該函數便可,此時能夠經過語句編程

from 模塊名 import 函數名1,函數名2....json

例:windows

import module
#從某個模塊導入某個功能
from module.xx.xx import xx
#從某個模塊導入某個功能,而且給他個別名
from module.xx.xx import xx as rename  
#從某個模塊導入全部
from module.xx.xx import *

 模塊分爲三種api

  • 自定義模塊
  • 內置模塊
  • 開源模塊

#安裝模塊的幾種方式app

(1)yum,pip安裝:http://www.ttlsa.com/python/how-to-install-and-use-pip-ttlsa/

(2)源碼安裝

須要編譯環境:yum install python-devel gcc
下載源碼包:wget http://xxxxxxxxxxx.tar
解壓:tar -xvf xxx.tar
進入:cd xxx
編譯:python setup.py build
安裝:python setup.py install

自定義模塊導入

1.在Python中,每一個Python文件均可以做爲一個模塊,模塊的名字就是文件的名字。

寫一個自定義模塊(模塊文件要和調用該模塊的程序在同一目錄下)

#s4.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#  Author: Jason Wang

def login():
    print("login")

def logout():
    print('logout')

 

#執行s3輸出: login

2.模塊文件爲單獨文件夾,文件夾和程序在同一目錄

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

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

3.sys.path添加目錄

若是sys.path路徑列表沒有你想要的路徑,能夠經過 sys.path.append('路徑') 添加。
經過os模塊能夠獲取各類目錄,若是自定義模塊的目錄機構包含兩級文件目錄,能夠將第一級父目錄加到path變量中例如:

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
#os.path.abspath(__file__)獲取文件的絕對路徑,os.path.dirname獲取此文件的父目錄,此例子爲將Atm_shopping加入到系統path路徑中去

  內置模塊

1.os模塊 提供系統級別的操做

os.getcwd() 獲取當前工做目錄,即當前python腳本工做的目錄路徑

>>> os.getcwd()
'/Users/JasonWang/PycharmProjects/sd13'

 os.chdir("目錄名") 改變當前腳本工做目錄;至關於linux下cd命令

>>> os.chdir('/usr')
>>> os.getcwd()
'/usr'
>>> 

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

>>> os.curdir
'.'

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

>>> os.pardir
'..'

 os.makedirs('目錄1/目錄2') 可生成多層遞歸目錄(至關於linux下mkdir -p)

>>> os.makedirs('test/a1')
>>> os.listdir()
['__pycache__', 'account.py', 'commons.py', 'index.py', 'manager.py', 'maopao.py', 'test']

 os.removedirs('目錄') 若目錄爲空,則刪除,並遞歸到上一級目錄,如若也爲空,則刪除,依此類推

>>> os.removedirs('test/a1')
>>> os.listdir()
['__pycache__', 'account.py', 'commons.py', 'index.py', 'manager.py', 'maopao.py']
>>> 
#a目錄中除了有一個b目錄外,再沒有其它的目錄和文件。
#b目錄中必須是一個空目錄。 若是想實現相似rm -rf的功能可使用shutil模塊

 os.mkdir('目錄') 生成單級目錄;至關於shell中mkdir 目錄

>>> os.mkdir('test')
>>> os.listdir()
['__pycache__', 'account.py', 'commons.py', 'index.py', 'manager.py', 'maopao.py', 'test']

 os.rmdir('目錄') 刪除單級空目錄,若目錄不爲空則沒法刪除,報錯;至關於shell中rmdir

>>> os.rmdir('test')
>>> os.listdir()
['__pycache__', 'account.py', 'commons.py', 'index.py', 'manager.py', 'maopao.py']

 os.listdir('目錄') 列出指定目錄下的全部文件和子目錄,包括隱藏文件,並以列表方式打印

os.remove()刪除一個文件

os.rename("原名","新名") 重命名文件/目錄

>>> os.rename('test','test1')
>>> os.listdir()
['__pycache__', 'account.py', 'commons.py', 'index.py', 'manager.py', 'maopao.py', 'test1']

os.stat('path/filename') 獲取文件/目錄信息

>>> os.stat('test1')
os.stat_result(st_mode=16877, st_ino=2841750, st_dev=16777220, st_nlink=2, st_uid=501, st_gid=20, st_size=68, st_atime=1465982539, st_mtime=1465982462, st_ctime=1465982462)
>>> 

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

>>> os.sep
'/'

 os.pathsep 輸出用於分割文件路徑的字符串

>>> os.pathsep ':'

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

>>> os.name
'posix'

 os.system("linux命令") 運行shell命令,直接顯示

>>> os.system('uptime')
 9:38  up 15 mins, 1 user, load averages: 2.24 2.55 2.02
0

os.environ 系統環境變量

>>> os.environ

 os其餘語法

os.path模塊主要用於文件的屬性獲取,
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所指向的文件或者目錄的最後修改時間

  二、sys模塊 用於提供對解釋器相關的操做

sys.argv   命令行參數List,第一個元素是程序自己路徑
sys.modules 返回系統導入的模塊字段,key是模塊名,value是模塊
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.modules.keys() 返回全部已經導入的模塊名
sys.modules.values() 返回全部已經導入的模塊
sys.exc_info()     獲取當前正在處理的異常類,exc_type、exc_value、exc_traceback當前處理的異常詳細信息
sys.exit(n)        退出程序,正常退出時exit(0)
sys.hexversion     獲取Python解釋程序的版本值,16進制格式如:0x020403F0
sys.version        獲取Python解釋程序的
sys.api_version    解釋器的C的API版本
sys.version_info
‘final’表示最終,也有’candidate’表示候選,serial表示版本級別,是否有後繼的發行
sys.displayhook(value)      若是value非空,這個函數會把他輸出到sys.stdout,而且將他保存進__builtin__._.指在python的交互式解釋器裏,’_’ 表明上次你輸入獲得的結果,hook是鉤子的意思,將上次的結果鉤過來
sys.getdefaultencoding()    返回當前你所用的默認的字符編碼格式
sys.getfilesystemencoding() 返回將Unicode文件名轉換成系統文件名的編碼的名字
sys.setdefaultencoding(name)用來設置當前默認的字符編碼,若是name和任何一個可用的編碼都不匹配,拋出 LookupError,這個函數只會被site模塊的sitecustomize使用,一旦別site模塊使用了,他會從sys模塊移除
sys.builtin_module_names    Python解釋器導入的模塊列表
sys.executable              Python解釋程序路徑
sys.getwindowsversion()     獲取Windows的版本
sys.copyright      記錄python版權相關的東西
sys.byteorder      本地字節規則的指示器,big-endian平臺的值是’big’,little-endian平臺的值是’little’
sys.exc_clear()    用來清除當前線程所出現的當前的或最近的錯誤信息
sys.exec_prefix    返回平臺獨立的python文件安裝的位置
sys.stderr         錯誤輸出
sys.stdin          標準輸入
sys.stdout         標準輸出
sys.platform       返回操做系統平臺名稱
sys.path           返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值
sys.maxunicode     最大的Unicode值
sys.maxint         最大的Int值
sys.version        獲取Python解釋程序的版本信息
sys.hexversion     獲取Python解釋程序的版本值,16進制格式如:0x020403F0

 3.時間模塊

1)time模塊

時間戳計算機時間的一種表示方式,是指格林威治時間1970年01月01日00時00分00秒(北京時間1970年01月01日08時00分00秒)起至如今的總秒數。

time.time()

>>> import time
>>> time.time()
1466041557.853502

time.ctime()

>>> time.ctime()#將時間戳轉化爲字符串格式Thu Jun 16 09:49:10 2016,默認是當前系統時間的時間戳
'Thu Jun 16 09:49:10 2016'
>>> time.ctime(time.time()-3600)#ctime能夠接收一個時間戳做爲參數,返回該時間戳的字符串形式 Wed Thu Jun 16 08:49:33 2016'
'Thu Jun 16 08:49:33 2016'

 time.gtime()

>>> time.gmtime()#將時間戳轉化爲struct_time格式,默認是當前系統時間戳
time.struct_time(tm_year=2016, tm_mon=6, tm_mday=16, tm_hour=1, tm_min=52, tm_sec=57, tm_wday=3, tm_yday=168, tm_isdst=0)
>>> time.gmtime(time.time()-3600)
time.struct_time(tm_year=2016, tm_mon=6, tm_mday=16, tm_hour=0, tm_min=53, tm_sec=18, tm_wday=3, tm_yday=168, tm_isdst=0)
說明:
struct_time格式也是一種時間表現形式,其實有點相似列表或元祖的形式
共有九個元素,分別表示,同一個時間戳的struct_time會由於時區不一樣而不一樣順序爲
年 tm_year
月 tm_mon
日 tm_mday
小時 tm_hour
分鐘 tm_min
秒 tm_sec
周 tm_wday,注意周是從0開始計數的,也就是週一是0
一年中的第幾天 tm_yday
是不是夏令日 tm_isdst(也沒啥卵用)

 time.localtime()

>>> time.localtime()# 一樣是將時間戳轉化爲struct_time,只不過顯示的是本地時間,gmtime顯示的是標準時間(格里尼治時間)
time.struct_time(tm_year=2016, tm_mon=6, tm_mday=16, tm_hour=9, tm_min=55, tm_sec=24, tm_wday=3, tm_yday=168, tm_isdst=0)

 time.mktime()

>>> time.mktime(time.localtime())# 將struct_time時間格式轉化爲時間戳
1466042217.0

 time.strftime()

>>> time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())# 將struct_time時間格式轉化爲自定義的字符串格式
'2016-06-16 09:58:43'
說明:
"%Y-%m-%d %H:%M:%S"就是咱們自定義的字符串個"%Y有點相似於佔位符

 time.strptime()

>>> time.strptime("2016-06-16","%Y-%m-%d")# 與trftime相反,將字符串格式轉化爲struct_time格式
time.struct_time(tm_year=2016, tm_mon=6, tm_mday=16, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=168, tm_isdst=-1)
說明:
第一個參數是時間的字符串形式,第二個參數是第一個參數的格式,格式要與字符串對應
另外時分秒默認是0,能夠省略,可是年月日不能夠省

 time.asctime()

>>> time.asctime(time.localtime())# 將struct_time轉化爲字符串形式
'Thu Jun 16 10:05:42 2016'

 datetime模塊

  • datetime.date:表示日期的類。經常使用的屬性有year, month, day
  • datetime.time:表示時間的類。經常使用的屬性有hour, minute, second, microsecond
  • datetime.datetime:表示日期時間
  • datetime.timedelta: 表示時間間隔,即兩個時間點之間的長度
datetime.date.today()
>>> datetime.date.today()# 返回當前日期的字符串形式2016-02-17
datetime.date(2016, 6, 16)
>>> print(datetime.date.today())
2016-06-16
datetime.datetime.now()
>>> print( datetime.datetime.now())#返回的時間的字符串形式
2016-06-16 10:10:37.612443
>>> print( datetime.datetime.now().timestamp())# 轉化爲struct_time格式
1466043058.141845
 datetime.date.fromtimestamp()

 

>>> datetime.date.fromtimestamp(time.time()- 3600 *24)
datetime.date(2016, 6, 15)
>>> print(datetime.date.fromtimestamp(time.time()- 3600 *24))
2016-06-15

  datetime.timedelta()

datetime.timedelta()返回的是一時間間隔對象,常與datetime.datetime.now()合用計算時間

>>> print(datetime.datetime.now() - datetime.timedelta(days = 2))
2016-06-14 10:27:09.652336

 3、遞歸

    在函數內部,能夠調用其餘函數。若是一個函數在內部調用自身自己,這個函數就是遞歸函數。遞歸算法對解決一大類問題是十分有效的,它每每使算法的描述簡潔並且易於理解。
遞歸算法解決問題的特色:
(1) 遞歸就是在過程或函數裏調用自身。
(2) 在使用遞歸策略時,必須有一個明確的遞歸結束條件,稱爲遞歸出口。
(3) 遞歸算法解題一般顯得很簡潔,但遞歸算法解題的運行效率較低。因此通常不提倡用遞歸算法設計程序。
(4) 在遞歸調用的過程中系統爲每一層的返回點、局部量等開闢了棧來存儲。遞歸次數過多容易形成棧溢出等。因此通常不提倡用遞歸算法設計程序。
遞歸算法所體現的「重複」通常有三個要求:
(1) 每次調用在規模上都有所縮小(一般是減半);
(2) 相鄰兩次重複之間有緊密的聯繫,前一次要爲後一次作準備(一般前一次的輸出就做爲後一次的輸入);
(3) 在問題的規模極小時必須用直接給出解答而再也不進行遞歸調用,於是每次遞歸調用都是有條件的(以規模未達到直接解答的大小爲條件),無條件遞歸調用將會成爲死循環而不能正常結束。
遞歸函數
def d():
    return "123"
def c():
    r = d()
    return r
def b():
    r = c()
    return r
def a():
    r = b()
    print(r)
a()
#123
def func(n):
    n += 1
    if n >=4:
        return 'end'
    return func(n)
r = func(1)
print(r)
#end
#階乘遞歸
def func(num):
    if num == 1:
        return 1
    return num*func(num-1)
a = func(7)
print(a)
#5040

實例,經過遞歸實現二分查找

1 def binary_search(data_list,find_num):
 2     mid_pos = int(len(data_list) /2 ) # 獲取中間的索引
 3     mid_val = data_list[mid_pos] # 獲取中間的索引對相應元素,也就是值
 4     print(data_list)
 5     if len(data_list) >1: # 遞歸結束條件,也就是規模績效
 6         if mid_val > find_num: # 中間的值比要找的值大,說明在中間值左邊
 7             print("[%s] should be in left of [%s]" %(find_num,mid_val))
 8             binary_search(data_list[:mid_pos],find_num) # 遞歸本身,繼續查找本身的左邊(也就是遞歸要求裏的縮小調用規模)
 9         elif mid_val < find_num: # 中間的值比要找的值大,說明在中間值左邊
10             print("[%s] should be in right of [%s]" %(find_num,mid_val))
11             binary_search(data_list[mid_pos + 1:],find_num)
12         else: # 若是既不大於也不小於說明正好等於
13             print("Find ", find_num)
14  
15     else:
16         # 當列表的大小等於1的時候,不在調用本身,結束遞歸
17         if mid_val == find_num: # 判斷最用一個元素是否等於要查找的數
18             print("Find ", find_num)
19         else:
20             print("cannot find [%s] in data_list" %find_num)
21  
22 if __name__ == '__main__':
23     primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103,104]
24     binary_search(primes,5)
25     binary_search(primes,66)

 執行結果

1 [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 104]
 2 [5] should be in left of [47]
 3 [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43]
 4 [5] should be in left of [19]
 5 [2, 3, 5, 7, 11, 13, 17]
 6 [5] should be in left of [7]
 7 [2, 3, 5]
 8 [5] should be in right of [3]
 9 [5]
10 Find  5
11 [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 104]
12 [66] should be in right of [47]
13 [53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 104]
14 [66] should be in left of [79]
15 [53, 59, 61, 67, 71, 73]
16 [66] should be in left of [67]
17 [53, 59, 61]
18 [66] should be in right of [59]
19 [61]
20 cannot find [66] in data_list
複製代碼

 logging模塊  

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

最簡單用法

>>> import logging
>>> logging.warning("user [Jason] attempted wrong password more than 5 times")
WARNING:root:user [Jason] attempted wrong password more than 5 times

可見,默認狀況下python的logging模塊將日誌打印到了標準輸出中,且只顯示了大於等於WARNING級別的日誌,
這說明默認的日誌級別設置爲WARNING(日誌級別等級CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET)

默認的日誌格式爲:日誌級別:Logger名稱:用戶輸出消息

 看一下這幾個日誌級別分別表明什麼意思

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.

 若是想把日誌寫到文件裏,也很簡單

import logging
logging.basicConfig(filename='test.log',level=logging.INFO)
logging.debug('This message should come to log files')
logging.info('come in this')
logging.warning('hey it came out')

 

 其中下面這句中的level=loggin.INFO意思是,把日誌紀錄級別設置爲INFO,也就是說,只有比日誌是INFO或比INFO級別更高的日誌纔會被紀錄到文件裏,在這個例子, 第一條日誌是不會被紀錄的,若是但願紀錄debug的日誌,那把日誌級別改爲DEBUG就好了。

感受上面的日誌格式忘記加上時間啦,日誌不知道時間怎麼行呢,下面就來加上!

import logging
logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
logging.warning('is when this event was logged.')
 
#輸出
12/12/2010 11:46:36 AM is when this event was logged.

2.靈活配置日誌級別,日誌格式,輸出位置

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(後邊會具體講解handler的概念),這樣日誌會被存儲在指定的文件中。

filemode:   文件打開方式,在指定了filename時使用這個參數,默認值爲「a」還可指定爲「w」。

format:     指定handler使用的日誌顯示格式。

datefmt:    指定日期時間格式。(datefmt='%a, %d %b %Y %H:%M:%S',%p)

level:      設置rootlogger(後邊會講解具體概念)的日誌級別

stream:     用指定的stream建立StreamHandler。能夠指定輸出到sys.stderr,sys.stdout或者文件,默認爲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             用戶輸出的消息

若是想同時把log打印在屏幕和文件日誌裏,就須要瞭解一點複雜的知識 了

 

The logging library takes a modular approach and offers several categories of components: loggers, handlers, filters, and formatters.

  • Loggers expose the interface that application code directly uses.
  • Handlers send the log records (created by loggers) to the appropriate destination.
  • Filters provide a finer grained facility for determining which log records to output.
  • Formatters specify the layout of log records in the final output.
import logging
 
#create logger
logger = logging.getLogger('TEST-LOG')
logger.setLevel(logging.DEBUG)
 
 
# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
 
# create file handler and set level to warning
fh = logging.FileHandler("access.log")
fh.setLevel(logging.WARNING)
# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
 
# add formatter to ch and fh
ch.setFormatter(formatter)
fh.setFormatter(formatter)
 
# add ch and fh to logger
logger.addHandler(ch)
logger.addHandler(fh)
 
# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')

3.Logger,Handler,Formatter,Filter的概念

logging.basicConfig()(用默認日誌格式(Formatter)爲日誌系統創建一個默認的流處理器(StreamHandler),
設置基礎配置(如日誌級別等)並加到root logger(根Logger)中)這幾個logging模塊級別的函數,
另外還有一個模塊級別的函數是logging.getLogger([name])(返回一個logger對象,若是沒有指定名字將返回root logger)

1).logging庫提供了多個組件:Logger、Handler、Filter、Formatter。

Logger       對象提供應用程序可直接使用的接口,
Handler      發送日誌到適當的目的地,
Filter          提供了過濾日誌信息的方法,
Formatter   指定日誌顯示格式。

# 建立一個logger
logger = logging.getLogger()
#建立一個帶用戶名的logger
logger1 = logging.getLogger('Jasonlog')
#設置一個日誌級別
logger.setLevel(logging.INFO)
logger1.setLevel(logging.INFO)
#建立一個handler,用於寫入日誌文件
fh = logging.FileHandler('test.log')
# 再建立一個handler,用於輸出到控制檯
ch = logging.StreamHandler()
# 定義handler的輸出格式formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
# 給logger添加handler
#logger.addFilter(filter)
logger.addHandler(fh)
logger.addHandler(ch)
# 給logger1添加handler
#logger1.addFilter(filter)
logger1.addHandler(fh)
logger1.addHandler(ch)
#給logger添加日誌
logger.info('logger info message')
logger1.info('logger1 info message')

 

 json & pickle模塊

用於序列化的兩個模塊

  • json,用於字符串 和 python數據類型間進行轉換
  • pickle,用於python特有的類型 和 python的數據類型間進行轉換

Json模塊提供了四個功能:dumps、dump、loads、load

pickle模塊提供了四個功能:dumps、dump、loads、load

# import json
# dic = {'k1':'v1'}
# print(dic,type(dic))
# #將python的基本類型轉換爲字符串
# result = json.dumps(dic)
# print(result,type(result))
{'k1': 'v1'} <class 'dict'>
{"k1": "v1"} <class 'str'>
s1 = '{"k1":123}'
import json
dic = json.loads(s1) #存入內存中
print(dic,type(dic))
{'k1': 123} <class 'dict'>
import requests
import json
response = requests.get('http://wthrcdn.etouch.cn/weather_mini?city=北京')
response.encoding = 'utf-8'
print(response)
#輸出
#<Response [200]>
dic = json.loads(response.text)#**使用雙引號
print(dic)
print(type(dic))
#輸出
{'desc': 'OK', 'data': {'wendu': '30', 'aqi': '125', 'city': '北京', 'forecast': [{'type': '多雲', 'low': '低溫 18℃', 'fengli': '微風級', 'date': '5日星期天', 'high': '高溫 30℃', 'fengxiang': '無持續風向'}, {'type': '多雲', 'low': '低溫 20℃', 'fengli': '微風級', 'date': '6日星期一', 'high': '高溫 30℃', 'fengxiang': '無持續風向'}, {'type': '雷陣雨', 'low': '低溫 16℃', 'fengli': '微風級', 'date': '7日星期二', 'high': '高溫 24℃', 'fengxiang': '無持續風向'}, {'type': '晴', 'low': '低溫 21℃', 'fengli': '微風級', 'date': '8日星期三', 'high': '高溫 31℃', 'fengxiang': '無持續風向'}, {'type': '晴', 'low': '低溫 22℃', 'fengli': '微風級', 'date': '9日星期四', 'high': '高溫 33℃', 'fengxiang': '無持續風向'}], 'ganmao': '各項氣象條件適宜,發生感冒機率較低。但請避免長期處於空調房間中,以防感冒。', 'yesterday': {'fx': '無持續風向', 'type': '陰', 'low': '低溫 19℃', 'fl': '微風', 'date': '4日星期六', 'high': '高溫 30℃'}}, 'status': 1000}
<class 'dict'>
 
import json
li = [11,22,33]
json.dump(li,open('db','w'))#序列化
li = json.load(open('db','r'))##將字符產反序列化,讀文件
print(type(li),li)
#輸出
#<class 'list'> [11, 22, 33]json/pickle
比較json更加適合跨語言,字符串,基本數據類型
class Foo():
    def f1(self):
        print('test')
import json
a = Foo
r = json.loads(a)
print(r)

 TypeError: the JSON object must be str, not 'type'

pickle,python複雜類型序列化,僅適用於python

import pickle
li = [11,22,33]
r = pickle.dumps(li)
print(r)
#b'\x80\x03]q\x00(K\x0bK\x16K!e.'
result = pickle.loads(r)
print(result)
#[11, 22, 33]
import pickle
li = [11,22,33]
pickle.dump(li, open('db','wb'))
result = pickle.load(open('db','rb'))
print(result)
#[11, 22, 33]

 

雙層裝飾器

User_INFO = {}

def check_login(func):
    def inner(*args,**kwargs):
        if User_INFO.get('is_login',None):
            ret = func(*args, **kwargs)
            return ret
        else:
            print('請登陸')

    return inner

def check_admin(func):
    def inner(*args,**kwargs):
        if User_INFO.get('user_type',None) == 2:
            ret = func(*args,**kwargs)
            return ret
        else:
            print("無權限查看")
    return inner
@check_login
@check_admin
def index():
    print("login success")
@check_login
def login():
    User_INFO['is_login'] = 'True'
    print("普通用戶登陸")

def search():
    print("")
def main():
    while True:
        inp = input("1.登陸2.查看3.後臺登陸")
        if inp == '1':
            User_INFO['is_login'] = True
            login()
        elif inp == '2':
            search()
        elif inp == '3':
            User_INFO['user_type'] = 2
            index()

main()

 經常使用格式化

 

字符串格式化
s = "alex %"
print(s)
#alex %

tp1 = "i am %s age %d" %("alex",18)
print(tp1)
##i am alex age 18
tp2 = "i am %(name)s age %(age)d" % {"name":"alex","age":17}
print(tp2)
#i am alex age 17
tp3 = "percent %.2f" % 99.2234234
print(tp3)
#percent 99.22
tp4 = "i am %(pp).2f %%" % {"pp": 123.42556,}
print(tp4)
#i am 123.43 %
tp4 = "i am %.2f %%" % (123.42556,)
print(tp4)
#i am 123.43 %

 

#format方法

s1 = "adassfdad{0}fads{0}1232{1}".format(123,"Jason")
print(s1)
#adassfdad123fads1231232Jason
s2 = "---{:*^20s}==={:+d}===={:x}".format('alex',12,5)
print(s2)
#---********alex********===+12====5

tp1 = "i am {}, age {}, {}".format("seven", 18, 'alex')
tp2 = "i am {}, age {}, {}".format(*["seven", 18, 'alex'])
print(tp1)
#i am seven, age 18, alex
print(tp2)
#i am seven, age 18, alex
tp3 = "numbers: {:b},{:o},{:d},{:x},{:x}, {:.4%}".format(15,15,15,15,15,34.667)
print(tp3)
#numbers: 1111,17,15,f,f, 3466.7000%
tp3 = "numbers: {:#b},{:#o},{:#d},{:#x},{:#x}, {:.4%}".format(15,15,15,15,15,34.667)
print(tp3)
#numbers: 0b1111,0o17,15,0xf,0xf, 3466.7000%

生成器迭代器

生成器
def func():
    yield 1
    yield 2
    yield 3
ret = func()
for i in ret:
    print(i)
# 1
# 2
# 3
def func():
    print(111)
    yield 1
    print(222)
    yield 2
    print(333)
    yield 3
ret = func()
print(ret)
r1 = ret.__next__()#進入yield函數,湖區yield後面的數據
print(r1)
r2 = ret.__next__()#進入yield函數,湖區yield後面的數據
print(r2)
r3 = ret.__next__()#進入yield函數,湖區yield後面的數據
print(r3)
輸出:
#<generator object func at 0x101a82830>
# 111
# 1
# 222
# 2
# 333
# 3
def myrange(arg):
    start = 0
    while True:
        if start > arg:
            return
        yield start
        start += 1
ret = myrange(3)
r = ret.__next__()
print(r)
r = ret.__next__()
print(r)
r = ret.__next__()
print(r)
#012
相關文章
相關標籤/搜索