Python/Standard Library

os模塊 編輯

os模塊就是對作業系統進行操作

  • os.remove() 刪除文件
  • os.unlink() 刪除文件
  • os.rename() 重命名文件
  • os.listdir() 列出指定目錄下所有文件
  • os.chdir() 改變當前工作目錄
  • os.getcwd() 獲取當前文件路徑
  • os.mkdir() 新建目錄
  • os.rmdir() 刪除空目錄(刪除非空目錄, 使用shutil.rmtree())
  • os.makedirs() 創建多級目錄
  • os.removedirs() 刪除多級目錄
  • os.stat(file) 獲取文件屬性
  • os.chmod(file) 修改文件權限
  • os.utime(file) 修改文件時間戳
  • os.name(file) 獲取作業系統標識
  • os.system() 執行作業系統命令
  • os.execvp() 啟動一個新進程
  • os.fork() 獲取父進程ID,在子進程返回中返回0
  • os.execvp() 執行外部程序腳本(Uinx)
  • os.spawn() 執行外部程序腳本(Windows)
  • os.access(path, mode) 判斷文件權限(詳細參考cnblogs)
  • os.wait() 暫時未知
  • os.open()
  • os.walk() 生成目錄樹下的所有文件名
  • os.getenv() 獲取系統的環境變量
  • os.putenv() 將一個目錄添加到環境變量中(臨時增加僅對當前腳本有效)
  • os.exit() 退出終端的命令
  • os.curdir 表示當前文件夾的變量
  • os.pardir 表示上一層文件夾的變量
  • os.name 獲取代表作業系統的名稱字符串的變量
  • os.sep 獲取系統路徑間隔符號的變量
  • os.extsep 獲取文件名稱和後綴之間的間隔符號的變量
  • os.linesep 獲取作業系統的換行符號的變量
  • os.environ 用於獲取和設置系統環境變量的內置值的字典

os.path模塊 編輯

  • os.path.split(filename) 將文件路徑和文件名分割(會將最後一個目錄作為文件名而分離)
  • os.path.splitext(filename) 將文件路徑和文件擴展名分割成一個元組
  • os.path.dirname(filename) 返回文件路徑的目錄部分
  • os.path.basename(filename) 返回文件路徑的文件名部分
  • os.path.join(dirname,basename) 將文件路徑和文件名湊成完整文件路徑
  • os.path.abspath(name) 獲得絕對路徑
  • os.path.splitunc(path) 把路徑分割為掛載點和文件名
  • os.path.normpath(path) 規範path字符串形式
  • os.path.exists() 判斷文件或目錄是否存在
  • os.path.isabs() 如果path是絕對路徑,返回True
  • os.path.realpath(path) #返回path的真實路徑
  • os.path.relpath(path[, start]) #從start開始計算相對路徑
  • os.path.normcase(path) #轉換path的大小寫和斜槓
  • os.path.isdir() 判斷name是不是一個目錄,name不是目錄就返回false
  • os.path.isfile() 判斷name是不是一個文件,不存在返回false
  • os.path.islink() 判斷文件是否連接文件,返回boolean
  • os.path.ismount() 指定路徑是否存在且為一個掛載點,返回boolean
  • os.path.samefile() 是否相同路徑的文件,返回boolean
  • os.path.getatime() 返回最近訪問時間 浮點型
  • os.path.getmtime() 返回上一次修改時間 浮點型
  • os.path.getctime() 返回文件創建時間 浮點型
  • os.path.getsize() 返回文件大小 字節單位
  • os.path.commonprefix(list) #返回list(多個路徑)中,所有path共有的最長的路徑
  • os.path.lexists #路徑存在則返回True,路徑損壞也返回True
  • os.path.expanduser(path) #把path中包含的」~」和」~user」轉換成用戶目錄
  • os.path.expandvars(path) #根據環境變量的值替換path中包含的」$name」和」${name}」
  • os.path.sameopenfile(fp1, fp2) #判斷fp1和fp2是否指向同一文件
  • os.path.samestat(stat1, stat2) #判斷stat tuple stat1和stat2是否指向同一個文件
  • os.path.splitdrive(path) #一般用在windows下,返回驅動器名和路徑組成的元組
  • os.path.walk(path, visit, arg) #遍歷path,給每個path執行一個函數詳細見手冊
  • os.path.supports_unicode_filenames() 設置是否支持unicode路徑名

os.stat()返回的文件屬性列表 編輯

描述os.stat()返回的文件屬性列表中各值的意義

  • fileStats = os.stat(path) 獲取到的文件屬性列表
  • fileStats[stat.ST_MODE] 獲取文件的模式
  • fileStats[stat.ST_SIZE] 文件大小
  • fileStats[stat.ST_MTIME] 文件最後修改時間
  • fileStats[stat.ST_ATIME] 文件最後訪問時間
  • fileStats[stat.ST_CTIME] 文件創建時間
  • stat.S_ISDIR(fileStats[stat.ST_MODE]) 是否目錄
  • stat.S_ISREG(fileStats[stat.ST_MODE]) 是否一般文件
  • stat.S_ISLNK(fileStats[stat.ST_MODE]) 是否連接文件
  • stat.S_ISSOCK(fileStats[stat.ST_MODE]) 是否COCK文件
  • stat.S_ISFIFO(fileStats[stat.ST_MODE]) 是否命名管道
  • stat.S_ISBLK(fileStats[stat.ST_MODE]) 是否塊設備
  • stat.S_ISCHR(fileStats[stat.ST_MODE]) 是否字符設置

sys 模塊 編輯

  • sys.argv 命令行參數List,第一個元素是程序本身路徑
  • sys.path 返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值
  • sys.modules.keys() 返回所有已經導入的模塊列表
  • sys.modules 返回系統導入的模塊字段,key是模塊名,value是模塊
  • sys.exc_info() 獲取當前正在處理的異常類,exc_type、exc_value、exc_traceback當前處理的異常詳細信息
  • sys.exit(n) 退出程序,正常退出時exit(0)
  • sys.hexversion 獲取Python解釋程序的版本值,16進制格式如:0x020403F0
  • sys.version 獲取Python解釋程序的版本信息
  • sys.platform 返回作業系統平台名稱
  • sys.stdout 標準輸出
  • sys.stdout.write(『aaa『) 標準輸出內容
  • sys.stdout.writelines() 無換行輸出
  • sys.stdin 標準輸入
  • sys.stdin.read() 輸入一行
  • sys.stderr 錯誤輸出
  • sys.exc_clear() 用來清除當前線程所出現的當前的或最近的錯誤信息
  • sys.exec_prefix 返回平台獨立的python文件安裝的位置
  • sys.byteorder 本地字節規則的指示器,big-endian平台的值是『big『,little-endian平台的值是『little『
  • sys.copyright 記錄python版權相關的東西
  • sys.api_version 解釋器的C的API版本
  • sys.version_info 『final『表示最終,也有『candidate『表示候選,表示版本級別,是否有後繼的發行
  • sys.getdefaultencoding() 返回當前你所用的默認的字符編碼格式
  • sys.getfilesystemencoding() 返回將Unicode文件名轉換成系統文件名的編碼的名字
  • sys.builtin_module_names Python解釋器導入的內建模塊列表
  • sys.executable Python解釋程序路徑
  • sys.getwindowsversion() 獲取Windows的版本
  • sys.stdin.readline() 從標準輸入讀一行,sys.stdout.write(「a」) 屏幕輸出a
  • sys.setdefaultencoding(name) 用來設置當前默認的字符編碼(詳細使用參考文檔)
  • sys.displayhook(value) 如果value非空,這個函數會把他輸出到sys.stdout(詳細使用參考文檔)
  • sys.maxint 最大的Int值
  • sys.maxunicode 最大的Unicode值

time模塊 編輯

time模塊中時間表現的格式主要有三種:

  • timestamp時間戳,時間戳表示的是從1970年1月1日00:00:00開始按秒計算的偏移量
  • struct_time時間元組,共有九個元素組。可用下標索引或者字段名訪問。字段tm_zone為時區名字。字段tm_gmtoff為時區與UTC的偏移秒數。
  • format time 格式化時間,已格式化的結構使時間更具可讀性。包括自定義格式和固定格式。

獲取本地時區

  • time.daylight 是否處於夏令時
  • time.tzname時區名字list
  • time.timezone 時區與UTC的負值秒數
  • time.altzone 夏令時的負值秒數

獲取時間或者轉換格式的函數

  • time.mktime(timetupleobj) 將datetime元組對象轉為時間戳
  • time.time() 當前時間戳
  • time.localtime 由時間戳到結構化時間
  • time.gmtime 由時間戳到結構化時間
  • time.strptime 從字符串時間到結構化時間
  • time.strftime 從結構化時間到字符串時間
  • time.asctime 從結構化時間到字符串時間
  • time.ctime 從時間戳到字符串時間

format time結構化表示:

  • %a 本地(locale)簡化星期名稱
  • %A 本地完整星期名稱
  • %b 本地簡化月份名稱
  • %B 本地完整月份名稱
  • %c 本地相應的日期和時間表示
  • %d 一個月中的第幾天(01 - 31)
  • %H 一天中的第幾個小時(24小時制,00 - 23)
  • %I 第幾個小時(12小時制,01 - 12)
  • %j 一年中的第幾天(001 - 366)
  • %m 月份(01 - 12)
  • %M 分鐘數(00 - 59)
  • %p 本地am或者pm的相應符
  • %S 秒(01 - 61)
  • %U 一年中的星期數。(00 - 53星期天是一個星期的開始。)第一個星期天之前的所有天數都放在第0周。
  • %w 一個星期中的第幾天(0 - 6,0是星期天)
  • %W 和%U基本相同,不同的是%W以星期一為一個星期的開始。
  • %x 本地相應日期
  • %X 本地相應時間
  • %y 去掉世紀的年份(00 - 99)
  • %Y 完整的年份
  • %Z 時區的名字(如果不存在為空字符)
  • %% 『%』字符

datetime模塊 編輯

datatime模塊重新封裝了time模塊,提供更多接口,提供的類有:date,time,datetime,timedelta,tzinfo。

可表示的年份為1至9999

date類 編輯

構造函數:datetime.date(year, month, day)

靜態方法和字段:

  • date.max、date.min:date對象所能表示的最大、最小日期;
  • date.resolution:date對象表示日期的最小單位。這裏是天。
  • date.today():返回一個表示當前本地日期的date對象;
  • date.fromtimestamp(timestamp):根據給定的C語言時間戮,返回一個本地日期的date對象;
  • date.fromisoformat(date_string):參數格式為「YYYY-MM-DD」
  • date.fromisocalendar(year, week, day):從python3.8開始
  • date.fromordinal(ordinal):從公元1年1月1日開始的day數

方法和屬性:

d1 = date(2011,06,03)#date对象
d1.year、date.month、date.day:年、月、日;
d1.replace(year, month, day):生成一个新的日期对象,用参数指定的年,月,日代替原有对象中的属性。(原有对象仍保持不变)
d1.timetuple():返回日期对应的time.struct_time对象;等价于time.struct_time((d.year, d.month, d.day, 0, 0, 0, d.weekday(), yday, -1))
d1.weekday():返回weekday,如果是星期日,返回0;如果是星期一,返回1,以此类推;
d1.isoweekday():返回weekday,如果是星期一,返回1;如果是星期二,返回2,以此类推;
d1.isocalendar():返回格式如(year,week,weekday)的元组;
d1.isoformat():返回格式如'YYYY-MM-DD’的字符串;date.__str__()等效于该函数
d1.strftime(fmt):和time模块format相同。 date.__format__(format)等效于该函数
d1.toordinal():返回整型
d1.ctime():等价于time.ctime(time.mktime(d.timetuple()))。如'Wed Dec  4 00:00:00 2002'

time類 編輯

datetime.time(hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ) 
time.fromisoformat(time_string):如HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]
t1 = datetime.time(10,23,15)#time对象
t1.hour、t1.minute、t1.second、t1.microsecond:时、分、秒、微秒;
t1.tzinfo:时区信息;
t1.replace([ hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ] ):创建一个新的时间对象,用参数指定的时、分、秒、微秒代替原有对象中的属性(原有对象仍保持不变);
t1.isoformat():返回型如"HH:MM:SS"格式的字符串表示;
t1.strftime(fmt):同time模块中的format;

靜態方法和字段

time.min、time.max:time类所能表示的最小、最大时间。其中,time.min = time(0, 0, 0, 0), time.max = time(23, 59, 59, 999999);
time.resolution:时间的最小单位,这里是1微秒;

datetime類 編輯

datetime相當於date和time結合起來。

 datetime.datetime (year, month, day[ , hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ] );其中month和day都从1开始

靜態方法和字段

datetime.today():返回一个表示当前本地时间的datetime对象;
datetime.now([tz]):返回一个表示当前本地时间的datetime对象,如果提供了参数tz,则获取tz参数所指时区的本地时间;
datetime.utcnow():返回一个当前utc时间的datetime对象;#格林威治时间
datetime.fromtimestamp(timestamp[, tz]):根据时间戮创建一个datetime对象,参数tz指定时区信息;
datetime.utcfromtimestamp(timestamp):根据时间戮创建一个datetime对象;
datetime.fromordinal(ordinal)
datetime.combine(date, time):根据date和time,创建一个datetime对象;
datetime.fromisoformat(date_string):例如'2011-11-04T00:05:23.283+00:00' 其中T可以替换为任意单个字符
datetime.fromisocalendar(year, week, day)
datetime.strptime(date_string, format):将格式字符串转换为datetime对象;

方法和屬性

dt=datetime.now()#datetime对象
dt.year、month、day、hour、minute、second、microsecond、tzinfo:
dt.date():获取date对象;
dt.time():获取time对象;
dt.timetz()
dt.astimezone(tz=None):返回一个新的实例,其时区已经改变。如果参数为空,则使用本地时区。如果tzinfo成员为空,参数为非本地时区,则报错。如果tzinfo成员不为空,则改用参数指定的时区。
dt.replace ([ year[ , month[ , day[ , hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ] ] ] ]):替换各个数据成员
dt.timetuple(): 相当于:time.struct_time((d.year, d.month, d.day,d.hour, d.minute, d.second,d.weekday(), yday, dst))
dt.utctimetuple()
dt.toordinal():从公元1年元旦开始的天数
dt.timestamp():返回浮点数
dt.weekday():星期一为0
dt.isoweekday():星期一为1
dt.isocalendar():返回结果是三元组(年份,第几周,第几天)
dt.isoformat ([ sep] ) 
dt.ctime ():返回一个日期时间的C格式字符串,等效于time.ctime(time.mktime(dt.timetuple()));
dt.strftime (format)

在Include/datetime.h中記錄了datetime類的聲明實現:

/* Fields are packed into successive bytes, each viewed as unsigned and
 * big-endian, unless otherwise noted:
 *
 * byte offset
 *  0           year     2 bytes, 1-9999
 *  2           month    1 byte, 1-12
 *  3           day      1 byte, 1-31
 *  4           hour     1 byte, 0-23
 *  5           minute   1 byte, 0-59
 *  6           second   1 byte, 0-59
 *  7           usecond  3 bytes, 0-999999
 * 10
 */

...

/* # of bytes for year, month, day, hour, minute, second, and usecond. */
#define _PyDateTime_DATETIME_DATASIZE 10

...

/* The datetime and time types have hashcodes, and an optional tzinfo member,
 * present if and only if hastzinfo is true.
 */
#define _PyTZINFO_HEAD          \
    PyObject_HEAD               \
    Py_hash_t hashcode;         \
    char hastzinfo;             /* boolean flag */

...

/* All datetime objects are of PyDateTime_DateTimeType, but that can be
 * allocated in two ways too, just like for time objects above.  In addition,
 * the plain date type is a base class for datetime, so it must also have
 * a hastzinfo member (although it's unused there).
 */

...

#define _PyDateTime_DATETIMEHEAD        \
    _PyTZINFO_HEAD                      \
    unsigned char data[_PyDateTime_DATETIME_DATASIZE];

typedef struct
{
    _PyDateTime_DATETIMEHEAD
} _PyDateTime_BaseDateTime;     /* hastzinfo false */

typedef struct
{
    _PyDateTime_DATETIMEHEAD
    unsigned char fold;
    PyObject *tzinfo;
} PyDateTime_DateTime;          /* hastzinfo true */

datetime對象的尺寸為48位元組,其成員佈局為:

  • 8 字節引用計數
  • 8位元組類型指針
  • 8 字節緩存哈希
  • 1 字節「hastzinfo」標誌
  • 10 字節手動打包 unsigned char[10] 包含日期時間數據
  • 1 字節「摺疊」標誌 ( DST-related )
  • 4 字節填充,對齊 tzinfo 指針
  • 8 字節 tzinfo 指針

timedelta類 編輯

時間加減,使用timedelta可以很方便的在日期上做天days,小時hour,分鐘,秒,毫秒,微妙的時間計算,如果要計算月份則需要另外的辦法。

datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0):构造函数,所有参数可选,可为负值,可为浮点数。内部表示归一化为天、秒、微妙的组合。
dt = datetime.now()
#日期减一天
dt1 = dt + timedelta(days=-1)#昨天
dt2 = dt - timedelta(days=1)#昨天
dt3 = dt + timedelta(days=1)#明天
delta_obj = dt3-dt
print type(delta_obj),delta_obj#<type 'datetime.timedelta'> 1 day, 0:00:00
print delta_obj.days ,delta_obj.total_seconds()#1 86400.0

tzinfo時區類 編輯

tzinfo是關於時區信息的類。tzinfo是一個抽象類,所以不能直接被實例化。

 class UTC(tzinfo):
    """UTC"""
    def __init__(self,offset = 0):
        self._offset = offset

    def utcoffset(self, dt):
        return timedelta(hours=self._offset)

    def tzname(self, dt):
        return "UTC +%s" % self._offset

    def dst(self, dt): //夏时制
        return timedelta(hours=0)

 #北京时间
 beijing = datetime(2011,11,11,0,0,0,tzinfo = UTC(8))
 print "beijing time:",beijing
 #曼谷时间
 bangkok = datetime(2011,11,11,0,0,0,tzinfo = UTC(7))
 print "bangkok time",bangkok
 #北京时间转成曼谷时间
 print "beijing-time to bangkok-time:",beijing.astimezone(UTC(7))

 #计算时间差时也会考虑时区的问题
 timespan = beijing - bangkok
 print "时差:",timespan

timezone 編輯

timezone是tzinfo的子類。構造為datetime.timezone(datetime.timedelta(hours=8), name="Asina/Shanghai")

hashlib加密 編輯

hashlib主要提供字符加密功能,將md5和sha模塊整合到了一起,支持md5,sha1, sha224, sha256, sha384, sha512等算法。注意:hashlib 加密的字符串類型為二進制編碼,直接加密字符串會報錯:TypeError: Unicode-objects must be encoded before hashing

import hashlib
# ######## md5 ########
string = "beyongjie"
md5 = hashlib.md5()
md5.update(string.encode('utf-8'))     #注意转码
res = md5.hexdigest()
print("md5加密结果:",res)

# ######## sha1 ########
sha1 = hashlib.sha1()
sha1.update(string.encode('utf-8'))
res = sha1.hexdigest()
print("sha1加密结果:",res)

# ######## sha256 ########
sha256 = hashlib.sha256()
sha256.update(string.encode('utf-8'))
res = sha256.hexdigest()
print("sha256加密结果:",res)


# ######## sha384 ########
sha384 = hashlib.sha384()
sha384.update(string.encode('utf-8'))
res = sha384.hexdigest()
print("sha384加密结果:",res)

# ######## sha512 ########
sha512= hashlib.sha512()
sha512.update(string.encode('utf-8'))
res = sha512.hexdigest()
print("sha512加密结果:",res)

常用方法

  • hash.update(arg) 更新哈希對象以字符串參數, 注意:如果同一個hash對象重複調用該方法,則m.update(a); m.update(b) 等效於 m.update(a+b),看下面例子
  • hash.digest() 返回摘要,作為二進制數據字符串值,
  • hash.hexdigest() 返回摘要,作為十六進制數據字符串值,
  • hash.copy() 複製

以上加密算法雖然依然非常厲害,但時候存在缺陷,即:通過撞庫可以反解。所以,有必要對加密算法中添加自定義key再來做加密。

low = hashlib.md5()
low.update('ab'.encode('utf-8'))
res = low.hexdigest()
print("普通加密:",res)

high = hashlib.md5(b'beyondjie')
high.update('ab'.encode('utf-8'))
res = high.hexdigest()
print("采用key加密:",res)

在各大開放平台大的API接口過程中,無一例外都會用到計算簽名值(sig值)。而在各種計算簽名的方法中,經常被採用的就是HMAC-SHA1:HMAC,散列消息鑑別碼,基於密鑰的Hash算法認證協議。實現原理為:利用已經公開的Hash函數和私有的密鑰,來生成固定長度的消息鑑別碼;SHA1、MD5等Hash算法是比較常用的不可逆Hash簽名計算方法;BASE64,將任意序列的8位元組字符轉換為人眼無法直接識別的符號編碼的一種方法

             import hmac
             import hashlib
             import base64
             hmac.new(Token,data,hashlib.sha1).digest().encode('base64').rstrip()
  • Token:即接口的key
  • data:要加密的數據

logging模塊 編輯

logging模塊是Python內置的標準模塊,主要用於輸出運行日誌,可以設置輸出日誌的等級、日誌保存路徑、日誌文件回滾等;相比print,具備如下優點:

  • 可以通過設置不同的日誌等級,在release版本中只輸出重要信息,而不必顯示大量的調試信息;
  • print將所有信息都輸出到標準輸出中,嚴重影響開發者從標準輸出中查看其它數據;logging則可以由開發者決定將信息輸出到什麼地方,以及怎麼輸出;

logging模塊中的類 編輯

在Python的lib目錄下的logging子目錄下,有3個py文件,組成logging的主幹的幾個基礎類都在__init__.py中:

#主干代码
/usr/lib/python2.7/logging/__init__.py
#扩展的handler和config
/usr/lib/pyhon2.7/logging/config.py
/usr/lib/python2.7/loging/handlers.py
類名字 方法 說明
LogRecord 構造函數傳入所有信息
getMessage 返回具體內容
每行記下的日誌信息對應一條LogRecord,包含所有信息,如時間、代碼行號等,組成一個字典
Formatter
  • __init__(fmt=None, datefmt=None, style='%')
用於把一條日誌的字典中的信息,格式化輸出為文本。
Logger
  • Logger.setLevel()
  • Logger.addHandler() 和 Logger.removeHandler()
  • Logger.addFilter() 和 Logger.removeFilter()
  • Logger.debug(), Logger.info(), Logger.warning(), Logger.error(), Logger.critical()
  • Logger.exception()
  • Logger.log()
  1. 發送log信息
  2. 過濾log信息
  3. 把log信息傳給handler

getLogger()返回一個loggger,其參數指出在一個繼承結構中的哪一個logger。後代logger會把消息傳播給祖先logger。

Handler
  • setLevel()設定handler能處理的消息級別
  • setFormatter()
  • addFilter() 和 removeFilter()
作為基類,應該派生自己的類使用
示例 示例 示例
示例 示例 示例
示例 示例 示例
示例 示例 示例


控制台輸出日誌 編輯

import logging
logging.basicConfig((level=logging.DEBUG,
                format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                datefmt='%a, %d %b %Y %H:%M:%S',
                filename='myapp.log',
                filemode='w')
logger = logging.getLogger(__name__)

logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
logger.info("Finish")

運行時,控制台輸出:

2016-10-09 19:11:19,434 - __main__ - INFO - Start print log
2016-10-09 19:11:19,434 - __main__ - WARNING - Something maybe fail.
2016-10-09 19:11:19,434 - __main__ - INFO - Finish

logging中可以選擇很多消息級別,如debug、info、warning、error以及critical。通過賦予logger或者handler不同的級別,開發者就可以只輸出錯誤信息到特定的記錄文件,或者在調試時只記錄調試信息。例如,我們將logger的級別改為DEBUG,再觀察一下輸出結果:

logging.basicConfig(level = logging.DEBUG,format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s')

控制台輸出了debug的信息:

2016-10-09 19:12:08,289 - __main__ - INFO - Start print log
2016-10-09 19:12:08,289 - __main__ - DEBUG - Do something
2016-10-09 19:12:08,289 - __main__ - WARNING - Something maybe fail.
2016-10-09 19:12:08,289 - __main__ - INFO - Finish

logging.basicConfig函數各參數:

  • filename:指定日誌文件名;
  • filemode:和file函數意義相同,指定日誌文件的打開模式,'w'或者'a';
  • format:指定輸出的格式和內容,format可以輸出很多有用的信息,
    • %(levelno)s:打印日誌級別的數值
    • %(levelname)s:打印日誌級別的名稱
    • %(pathname)s:打印當前執行程序的路徑,其實就是sys.argv[0]
    • %(filename)s:打印當前執行程序名
    • %(funcName)s:打印日誌的當前函數
    • %(lineno)d:打印日誌的當前行號
    • %(asctime)s:打印日誌的時間
    • %(thread)d:打印線程ID
    • %(threadName)s:打印線程名稱
    • %(process)d:打印進程ID
    • %(message)s:打印日誌信息
  • datefmt:指定時間格式,同time.strftime();
  • level:設置日誌級別,默認為logging.WARNNING; CRITICAL = 50 ERROR = 40 WARNING = 30 INFO 20 DEBUG = 10 NOTEST = 0
  • stream:指定將日誌的輸出流,可以指定輸出到sys.stderr,sys.stdout或者文件,默認輸出到sys.stderr,當stream和filename同時指定時,stream被忽略;
   %(name)s            Name of the logger (logging channel)
   %(levelno)s         Numeric logging level for the message (DEBUG, INFO,
                       WARNING, ERROR, CRITICAL)
   %(levelname)s       Text logging level for the message ("DEBUG", "INFO",
                       "WARNING", "ERROR", "CRITICAL")
   %(pathname)s        Full pathname of the source file where the logging
                       call was issued (if available)
   %(filename)s        Filename portion of pathname
   %(module)s          Module (name portion of filename)
   %(lineno)d          Source line number where the logging call was issued
                       (if available)
   %(funcName)s        Function name
   %(created)f         Time when the LogRecord was created (time.time()
                       return value)
   %(asctime)s         Textual time when the LogRecord was created
   %(msecs)d           Millisecond portion of the creation time
   %(relativeCreated)d Time in milliseconds when the LogRecord was created,
                       relative to the time the logging module was loaded
                       (typically at application startup time)
   %(thread)d          Thread ID (if available)
   %(threadName)s      Thread name (if available)
   %(process)d         Process ID (if available)
   %(message)s         The result of record.getMessage(), computed just as
                       the record is emitted

將日誌寫入到文件 編輯

設置logging,創建一個FileHandler,並對輸出消息的格式進行設置,將其添加到logger,然後將日誌寫入到指定的文件中

import logging
logger = logging.getLogger(__name__)
logger.setLevel(level = logging.INFO)
handler = logging.FileHandler("log.txt")
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)

logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
logger.info("Finish")

將日誌同時輸出到屏幕和日誌文件 編輯

logger中添加StreamHandler,可以將日誌輸出到屏幕上

import logging
logger = logging.getLogger(__name__)
logger.setLevel(level = logging.INFO)
handler = logging.FileHandler("log.txt")
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)

console = logging.StreamHandler()
console.setLevel(logging.INFO)

logger.addHandler(handler)
logger.addHandler(console)

logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
logger.info("Finish")

可以發現,logging有一個日誌處理的主對象,其他處理方式都是通過addHandler添加進去,logging中包含的handler主要有如下幾種,

  • handler名稱 位置 作用
  • StreamHandler:logging.StreamHandler;日誌輸出到流,可以是sys.stderr,sys.stdout或者文件
  • FileHandler:logging.FileHandler;日誌輸出到文件
  • BaseRotatingHandler:logging.handlers.BaseRotatingHandler;基本的日誌回滾方式
  • RotatingHandler:logging.handlers.RotatingHandler;日誌回滾方式,支持日誌文件最大數量和日誌文件回滾
  • TimeRotatingHandler:logging.handlers.TimeRotatingHandler;日誌回滾方式,在一定時間區域內回滾日誌文件
  • SocketHandler:logging.handlers.SocketHandler;遠程輸出日誌到TCP/IP sockets
  • DatagramHandler:logging.handlers.DatagramHandler;遠程輸出日誌到UDP sockets
  • SMTPHandler:logging.handlers.SMTPHandler;遠程輸出日誌到郵件地址
  • SysLogHandler:logging.handlers.SysLogHandler;日誌輸出到syslog
  • NTEventLogHandler:logging.handlers.NTEventLogHandler;遠程輸出日誌到Windows NT/2000/XP的事件日誌
  • MemoryHandler:logging.handlers.MemoryHandler;日誌輸出到內存中的指定buffer
  • HTTPHandler:logging.handlers.HTTPHandler;通過"GET"或者"POST"遠程輸出到HTTP伺服器

日誌回滾 編輯

使用RotatingFileHandler,可以實現日誌回滾,

import logging
from logging.handlers import RotatingFileHandler
logger = logging.getLogger(__name__)
logger.setLevel(level = logging.INFO)
#定义一个RotatingFileHandler,最多备份3个日志文件,每个日志文件最大1K
rHandler = RotatingFileHandler("log.txt",maxBytes = 1*1024,backupCount = 3)
rHandler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
rHandler.setFormatter(formatter)

console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setFormatter(formatter)

logger.addHandler(rHandler)
logger.addHandler(console)

logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
logger.info("Finish")

可以在工程目錄中看到,備份的日誌文件:

2016/10/09  19:36               732 log.txt
2016/10/09  19:36               967 log.txt.1
2016/10/09  19:36               985 log.txt.2
2016/10/09  19:36               976 log.txt.3

設置消息的等級 編輯

可以設置不同的日誌等級,用於控制日誌的輸出,

  • 日誌等級:使用範圍
  • FATAL:致命錯誤
  • CRITICAL:特別糟糕的事情,如內存耗盡、磁盤空間為空,一般很少使用
  • ERROR:發生錯誤時,如IO操作失敗或者連接問題
  • WARNING:發生很重要的事件,但是並不是錯誤時,如用戶登錄密碼錯誤
  • INFO:處理請求或者狀態變化等日常事務
  • DEBUG:調試過程中使用DEBUG等級,如算法中每個循環的中間狀態

捕獲traceback 編輯

Python中的traceback模塊被用於跟蹤異常返回信息,可以在logging中記錄下traceback,

import logging
logger = logging.getLogger(__name__)
logger.setLevel(level = logging.INFO)
handler = logging.FileHandler("log.txt")
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)

console = logging.StreamHandler()
console.setLevel(logging.INFO)

logger.addHandler(handler)
logger.addHandler(console)

logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
try:
    open("sklearn.txt","rb")
except (SystemExit,KeyboardInterrupt):
    raise
except Exception:
    logger.error("Faild to open sklearn.txt from logger.error",exc_info = True)

logger.info("Finish")

控制台和日誌文件log.txt中輸出:

Start print log
Something maybe fail.
Faild to open sklearn.txt from logger.error
Traceback (most recent call last):
  File "G:\zhb7627\Code\Eclipse WorkSpace\PythonTest\test.py", line 23, in <module>
    open("sklearn.txt","rb")
IOError: [Errno 2] No such file or directory: 'sklearn.txt'
Finish

也可以使用logger.exception(msg,_args),它等價於logger.error(msg,exc_info = True,_args),將

logger.error("Faild to open sklearn.txt from logger.error",exc_info = True)

替換為,

logger.exception("Failed to open sklearn.txt from logger.exception")

控制台和日誌文件log.txt中輸出,

Start print log
Something maybe fail.
Failed to open sklearn.txt from logger.exception
Traceback (most recent call last):
  File "G:\zhb7627\Code\Eclipse WorkSpace\PythonTest\test.py", line 23, in <module>
    open("sklearn.txt","rb")
IOError: [Errno 2] No such file or directory: 'sklearn.txt'
Finish

多模塊使用logging 編輯

#主模块mainModule.py
import logging
import subModule
logger = logging.getLogger("mainModule")
logger.setLevel(level = logging.INFO)
handler = logging.FileHandler("log.txt")
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)

console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setFormatter(formatter)

logger.addHandler(handler)
logger.addHandler(console)


logger.info("creating an instance of subModule.subModuleClass")
a = subModule.SubModuleClass()
logger.info("calling subModule.subModuleClass.doSomething")
a.doSomething()
logger.info("done with  subModule.subModuleClass.doSomething")
logger.info("calling subModule.some_function")
subModule.som_function()
logger.info("done with subModule.some_function")
#子模块subModule.py,
import logging

module_logger = logging.getLogger("mainModule.sub")
class SubModuleClass(object):
    def __init__(self):
        self.logger = logging.getLogger("mainModule.sub.module")
        self.logger.info("creating an instance in SubModuleClass")
    def doSomething(self):
        self.logger.info("do something in SubModule")
        a = []
        a.append(1)
        self.logger.debug("list a = " + str(a))
        self.logger.info("finish something in SubModuleClass")

def som_function():
    module_logger.info("call function some_function")

執行之後,在控制和日誌文件log.txt中輸出,

2016-10-09 20:25:42,276 - mainModule - INFO - creating an instance of subModule.subModuleClass
2016-10-09 20:25:42,279 - mainModule.sub.module - INFO - creating an instance in SubModuleClass
2016-10-09 20:25:42,279 - mainModule - INFO - calling subModule.subModuleClass.doSomething
2016-10-09 20:25:42,279 - mainModule.sub.module - INFO - do something in SubModule
2016-10-09 20:25:42,279 - mainModule.sub.module - INFO - finish something in SubModuleClass
2016-10-09 20:25:42,279 - mainModule - INFO - done with  subModule.subModuleClass.doSomething
2016-10-09 20:25:42,279 - mainModule - INFO - calling subModule.some_function
2016-10-09 20:25:42,279 - mainModule.sub - INFO - call function some_function
2016-10-09 20:25:42,279 - mainModule - INFO - done with subModule.some_function

首先在主模塊定義了logger'mainModule',並對它進行了配置,就可以在解釋器進程裏面的其他地方通過getLogger('mainModule')得到的對象都是一樣的,不需要重新配置,可以直接使用。定義的該logger的子logger,都可以共享父logger的定義和配置,所謂的父子logger是通過命名來識別,任意以'mainModule'開頭的logger都是它的子logger,例如'mainModule.sub'。

實際開發一個application,首先可以通過logging配置文件編寫好這個application所對應的配置,可以生成一個根logger,如'PythonAPP',然後在主函數中通過fileConfig加載logging配置,接着在application的其他地方、不同的模塊中,可以使用根logger的子logger,如'PythonAPP.Core','PythonAPP.Web'來進行log,而不需要反覆的定義和配置各個模塊的logger。

通過JSON文件配置logging模塊 編輯

儘管可以在Python代碼中配置logging,但是這樣並不夠靈活,最好的方法是使用一個配置文件來配置。在Python 2.7及以後的版本中,可以從字典中加載logging配置,也就意味着可以通過JSON或者YAML文件加載日誌的配置。

JSON配置文件:

{
    "version":1,
    "disable_existing_loggers":false,
    "formatters":{
        "simple":{
            "format":"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
        }
    },
    "handlers":{
        "console":{
            "class":"logging.StreamHandler",
            "level":"DEBUG",
            "formatter":"simple",
            "stream":"ext://sys.stdout"
        },
        "info_file_handler":{
            "class":"logging.handlers.RotatingFileHandler",
            "level":"INFO",
            "formatter":"simple",
            "filename":"info.log",
            "maxBytes":"10485760",
            "backupCount":20,
            "encoding":"utf8"
        },
        "error_file_handler":{
            "class":"logging.handlers.RotatingFileHandler",
            "level":"ERROR",
            "formatter":"simple",
            "filename":"errors.log",
            "maxBytes":10485760,
            "backupCount":20,
            "encoding":"utf8"
        }
    },
    "loggers":{
        "my_module":{
            "level":"ERROR",
            "handlers":["info_file_handler"],
            "propagate":"no"
        }
    },
    "root":{
        "level":"INFO",
        "handlers":["console","info_file_handler","error_file_handler"]
    }
}

通過JSON加載配置文件,然後通過logging.dictConfig配置logging,

import json
import logging.config
import os

def setup_logging(default_path = "logging.json",default_level = logging.INFO,env_key = "LOG_CFG"):
    path = default_path
    value = os.getenv(env_key,None)
    if value:
        path = value
    if os.path.exists(path):
        with open(path,"r") as f:
            config = json.load(f)
            logging.config.dictConfig(config)
    else:
        logging.basicConfig(level = default_level)

def func():
    logging.info("start func")

    logging.info("exec func")

    logging.info("end func")

if __name__ == "__main__":
    setup_logging(default_path = "logging.json")
    func()

通過YAML文件配置logging模塊 編輯

通過YAML文件進行配置,比JSON看起來更加簡介明了

version: 1
disable_existing_loggers: False
formatters:
        simple:
            format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
handlers:
    console:
            class: logging.StreamHandler
            level: DEBUG
            formatter: simple
            stream: ext://sys.stdout
    info_file_handler:
            class: logging.handlers.RotatingFileHandler
            level: INFO
            formatter: simple
            filename: info.log
            maxBytes: 10485760
            backupCount: 20
            encoding: utf8
    error_file_handler:
            class: logging.handlers.RotatingFileHandler
            level: ERROR
            formatter: simple
            filename: errors.log
            maxBytes: 10485760
            backupCount: 20
            encoding: utf8
loggers:
    my_module:
            level: ERROR
            handlers: [info_file_handler]
            propagate: no
root:
    level: INFO
    handlers: [console,info_file_handler,error_file_handler]

通過YAML加載配置文件,然後通過logging.dictConfig配置logging,

import yaml
import logging.config
import os

def setup_logging(default_path = "logging.yaml",default_level = logging.INFO,env_key = "LOG_CFG"):
    path = default_path
    value = os.getenv(env_key,None)
    if value:
        path = value
    if os.path.exists(path):
        with open(path,"r") as f:
            config = yaml.load(f)
            logging.config.dictConfig(config)
    else:
        logging.basicConfig(level = default_level)

def func():
    logging.info("start func")

    logging.info("exec func")

    logging.info("end func")

if __name__ == "__main__":
    setup_logging(default_path = "logging.yaml")
    func()

subprocess模塊 編輯

subprocess是Python 2.4中新增的一個模塊,它允許生成新的進程,連接到它們的 input/output/error 管道,並獲取它們的返回(狀態)碼。這個模塊的目的在於替換幾個舊的模塊和方法,如:

   os.system
   os.spawn*
  • 使用的Python 2.4以上,但是是Python 3.5以下的版本,Python官方給出的建議是使用subprocess.call()函數。Python 2.5中新增了一個subprocess.check_call()函數,Python 2.7中新增了一個subprocess.check_output()函數,這兩個函數也可以按照需求進行使用。
  • 使用的是Python 3.5及以上的版本(目前應該還很少),Python官方給出的建議是儘量使用subprocess.run()函數。
  • 當subprocess.call()、subprocess.check_call()、subprocess.check_output()和subprocess.run()這些高級函數無法滿足需求時,我們可以使用subprocess.Popen類來實現我們需要的複雜功能。

subprocess模塊中的常用函數 編輯

  • 函數 描述
  • subprocess.run() Python 3.5中新增的函數。執行指定的命令,等待命令執行完成後返回一個包含執行結果的CompletedProcess類的實例。
  • subprocess.call() 執行指定的命令,返回命令執行狀態,其功能類似於os.system(cmd)。
  • subprocess.check_call() Python 2.5中新增的函數。 執行指定的命令,如果執行成功則返回狀態碼,否則拋出異常。其功能等價於subprocess.run(..., check=True)。
  • subprocess.check_output() Python 2.7中新增的的函數。執行指定的命令,如果執行狀態碼為0則返回命令執行結果,否則拋出異常。
  • subprocess.getoutput(cmd) 接收字符串格式的命令,執行命令並返回執行結果,其功能類似於os.popen(cmd).read()和commands.getoutput(cmd)。
  • subprocess.getstatusoutput(cmd) 執行cmd命令,返回一個元組(命令執行狀態, 命令執行結果輸出),其功能類似於commands.getstatusoutput()。

說明:

  • 在Python 3.5之後的版本中,官方文檔中提倡通過subprocess.run()函數替代其他函數來使用subproccess模塊的功能;
  • 在Python 3.5之前的版本中,我們可以通過subprocess.call(),subprocess.getoutput()等上面列出的其他函數來使用subprocess模塊的功能;
  • subprocess.run()、subprocess.call()、subprocess.check_call()和subprocess.check_output()都是通過對subprocess.Popen的封裝來實現的高級函數,因此如果我們需要更複雜功能時,可以通過subprocess.Popen來完成。
  • subprocess.getoutput()和subprocess.getstatusoutput()函數是來自Python 2.x的commands模塊的兩個遺留函數。它們隱式的調用系統shell,並且不保證其他函數所具有的安全性和異常處理的一致性。另外,它們從Python 3.3.4開始才支持Windows平台。

參數說明:

  • args: 要執行的shell命令,默認應該是一個字符串序列,如['df', '-Th']或('df', '-Th'),也可以是一個字符串,如'df -Th',但是此時需要把shell參數的值置為True。
  • shell: 如果shell為True,那麼指定的命令將通過shell執行。如果我們需要訪問某些shell的特性,如管道、文件名通配符、環境變量擴展功能,這將是非常有用的。當然,python本身也提供了許多類似shell的特性的實現,如glob、fnmatch、os.walk()、os.path.expandvars()、os.expanduser()和shutil等。
  • check: 如果check參數的值是True,且執行命令的進程以非0狀態碼退出,則會拋出一個CalledProcessError的異常,且該異常對象會包含 參數、退出狀態碼、以及stdout和stderr(如果它們有被捕獲的話)。

stdout, stderr:

  • run()函數默認不會捕獲命令執行結果的正常輸出和錯誤輸出,如果我們向獲取這些內容需要傳遞subprocess.PIPE,然後可以通過返回的CompletedProcess類實例的stdout和stderr屬性或捕獲相應的內容;
  • call()和check_call()函數返回的是命令執行的狀態碼,而不是CompletedProcess類實例,所以對於它們而言,stdout和stderr不適合賦值為subprocess.PIPE;
  • check_output()函數默認就會返回命令執行結果,所以不用設置stdout的值,如果我們希望在結果中捕獲錯誤信息,可以執行stderr=subprocess.STDOUT。
  • input: 該參數是傳遞給Popen.communicate(),通常該參數的值必須是一個字節序列,如果universal_newlines=True,則其值應該是一個字符串。
  • universal_newlines: 該參數影響的是輸入與輸出的數據格式,比如它的值默認為False,此時stdout和stderr的輸出是字節序列;當該參數的值設置為True時,stdout和stderr的輸出是字符串。

subprocess.CompletedProcess類 編輯

subprocess.run()函數是Python3.5中新增的一個高級函數,其返回值是一個subprocess.CompletedPorcess類的實例,因此,subprocess.completedPorcess類也是Python 3.5中才存在的。它表示的是一個已結束進程的狀態信息,它所包含的屬性如下:

  • args: 用於加載該進程的參數,這可能是一個列表或一個字符串
  • returncode: 子進程的退出狀態碼。通常情況下,退出狀態碼為0則表示進程成功運行了;一個負值-N表示這個子進程被信號N終止了
  • stdout: 從子進程捕獲的stdout。這通常是一個字節序列,如果run()函數被調用時指定universal_newlines=True,則該屬性值是一個字符串。如果run()函數被調用時指定stderr=subprocess.STDOUT,那麼stdout和stderr將會被整合到這一個屬性中,且stderr將會為None
  • stderr: 從子進程捕獲的stderr。它的值與stdout一樣,是一個字節序列或一個字符串。如果stderr滅有被捕獲的話,它的值就為None
  • check_returncode(): 如果returncode是一個非0值,則該方法會拋出一個CalledProcessError異常。

subprocess.Popen 編輯

該類用於在一個新的進程中執行一個子程序。前面我們提到過,上面介紹的這些函數都是基於subprocess.Popen類實現的,通過使用這些被封裝後的高級函數可以很方面的完成一些常見的需求。由於subprocess模塊底層的進程創建和管理是由Popen類來處理的,因此,當我們無法通過上面哪些高級函數來實現一些不太常見的功能時就可以通過subprocess.Popen類提供的靈活的api來完成。

subprocess.Popen的構造函數

class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, 
   preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False,
   startup_info=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=())

參數說明:

  • args: 要執行的shell命令,可以是字符串,也可以是命令各個參數組成的序列。當該參數的值是一個字符串時,該命令的解釋過程是與平台相關的,因此通常建議將args參數作為一個序列傳遞。
  • bufsize: 指定緩存策略,0表示不緩衝,1表示行緩衝,其他大於1的數字表示緩衝區大小,負數 表示使用系統默認緩衝策略。
  • stdin, stdout, stderr: 分別表示程序標準輸入、輸出、錯誤句柄。
  • preexec_fn: 用於指定一個將在子進程運行之前被調用的可執行對象,只在Unix平台下有效。
  • close_fds: 如果該參數的值為True,則除了0,1和2之外的所有文件描述符都將會在子進程執行之前被關閉。
  • shell: 該參數用於標識是否使用shell作為要執行的程序,如果shell值為True,則建議將args參數作為一個字符串傳遞而不要作為一個序列傳遞。
  • cwd: 如果該參數值不是None,則該函數將會在執行這個子進程之前改變當前工作目錄。
  • env: 用於指定子進程的環境變量,如果env=None,那麼子進程的環境變量將從父進程中繼承。如果env!=None,它的值必須是一個映射對象。
  • universal_newlines: 如果該參數值為True,則該文件對象的stdin,stdout和stderr將會作為文本流被打開,否則他們將會被作為二進制流被打開。
  • startupinfo和creationflags: 這兩個參數只在Windows下有效,它們將被傳遞給底層的CreateProcess()函數,用於設置子進程的一些屬性,如主窗口的外觀,進程優先級等。

subprocess.Popen類的實例可調用的方法

  • 方法 描述
  • Popen.poll() 用於檢查子進程(命令)是否已經執行結束,沒結束返回None,結束後返回狀態碼。
  • Popen.wait(timeout=None) 等待子進程結束,並返回狀態碼;如果在timeout指定的秒數之後進程還沒有結束,將會拋出一個TimeoutExpired異常。
  • Popen.communicate(input=None, timeout=None) 該方法可用來與進程進行交互,比如發送數據到stdin,從stdout和stderr讀取數據,直到到達文件末尾。
  • Popen.send_signal(signal) 發送指定的信號給這個子進程。
  • Popen.terminate() 停止該子進程。
  • Popen.kill() 殺死該子進程。

關於communicate()方法的說明:

  • 該方法中的可選參數 input 應該是將被發送給子進程的數據,或者如沒有數據發送給子進程,該參數應該是None。input參數的數據類型必須是字節串,如果universal_newlines參數值為True,則input參數的數據類型必須是字符串。
  • 該方法返回一個元組(stdout_data, stderr_data),這些數據將會是字節穿或字符串(如果universal_newlines的值為True)。
  • 如果在timeout指定的秒數後該進程還沒有結束,將會拋出一個TimeoutExpired異常。捕獲這個異常,然後重新嘗試通信不會丟失任何輸出的數據。但是超時之後子進程並沒有被殺死,為了合理的清除相應的內容,一個好的應用應該手動殺死這個子進程來結束通信。
  • 需要注意的是,這裏讀取的數據是緩衝在內存中的,所以,如果數據大小非常大或者是無限的,就不應該使用這個方法。

json 編輯

JSON(JavaScript Object Notation, JS 對象標記) 是一種輕量級的數據交換格式。JSON的數據格式其實就是python裏面的字典格式,裏面可以包含方括號括起來的數組,也就是python裏面的列表。在python中,有專門處理json格式的模塊—— json 和 picle模塊。json模塊和pickle模塊都有 dumps、dump、loads、load四種方法,而且用法一樣。json模塊序列化出來的是通用格式,就是普通的字符串;picle模塊序列化出來的只有python可以認識,其他程式語言不認識的,表現為亂碼。picle可以序列化函數,但是其他文件想用該函數,在該文件中需要有該文件的定義(定義和參數必須相同,內容可以不同)。

  • dumps只完成了序列化為str,
  • dump必須傳文件描述符,將序列化的str保存到文件中
  • loads 只完成了反序列化,
  • load 只接收文件描述符,完成了讀取文件和反序列化

python對象(obj) 與json對象的對應關係表:

   +-------------------+---------------+
   | Python            | JSON          |
   +===================+===============+
   | dict              | object        |
   +-------------------+---------------+
   | list, tuple       | array         |
   +-------------------+---------------+
   | str               | string        |
   +-------------------+---------------+
   | int, float        | number        |
   +-------------------+---------------+
   | True              | true          |
   +-------------------+---------------+
   | False             | false         |
   +-------------------+---------------+
   | None              | null          |
   +-------------------+---------------+

configparser 編輯

configparser 是 Python 標準庫中用來解析配置文件的模塊,並且內置方法和字典非常接近。Python2.x 中名為 ConfigParser,3.x 已更名小寫,並加入了一些新功能。configparser 默認支持=與:兩種分隔key/value的分隔符。

>>> import configparser
>>> config = configparser.ConfigParser()    # 首先需要初始化实例 注意大小写
>>> config.read("config.ini")   # 读取配置文件 配置文件的路径
["config.ini"]
>>> parser = configparser.ConfigParser() #或者可以直接读字典
>>> parser.read_dict({'section1': {'key1': 'value1',
...                                'key2': 'value2',
...                                'key3': 'value3'},
...                   'section2': {'keyA': 'valueA',
...                                'keyB': 'valueB',
...                                'keyC': 'valueC'},
...                   'section3': {'foo': 'x',
...                                'bar': 'y',
...                                'baz': 'z'}
... })

>>> config.sections() #获取所有 sections
['bitbucket.org', 'topsecret.com']    # 注意会过滤掉[DEFAULT]
>>> config.items('topsecret.com') #获取指定 section 的 keys & values
>>>> [('port', '50022'), ('forwardx11', 'no')]    # 注意items()返回的字符串会全变成小写
>>> config.options('topsecret.com') #获取指定 section 的 keys
['Port', 'ForwardX11']
>>> for option in config['topsecret.com']:
...     print(option)
Port
ForwardX11
>>> config['bitbucket.org']['User'] #获取指定 key 的 value
'Tom'
>>> config.get('bitbucket.org', 'User')
'Tom'
>>> config.getint('topsecret.com', 'Port')
50022
>>> 'DEFAULT' in config #检查
True
>>> 'test' in config['section_test']
False
>>> 'Tom' in config['bitbucket.org']['User']
True
>>> config.has_section('bitbucket.org')
True
>>> config.has_option('section_test', 'test')
False
>>> config.add_section('Section_1') #添加
>>> config.set('Section_1', 'key_1', 'value_1')    # 注意键值是用set()方法
>>> config.write(open('config.ini', 'w'))    # 一定要写入才生效
>>> config.remove_option('Section_1', 'key_1')#删除
True
>>> config.remove_section('Section_1')
True
>>> config.clear()  # 清空除[DEFAULT]之外所有内容
>>> config.write(open('config.ini', 'w'))

[DEFAULT] 一般包含 ini 格式配置文件的默認項,所以 configparser 部分方法會自動跳過這個 section 。 前面已經提到 sections() 是獲取不到的,還有刪除方法對 [DEFAULT] 也無效:但指定刪除和修改 [DEFAULT] 里的 keys & values 是可以的。has_section() 也無效,可以和 in (有效)區別使用。

shutil模塊 編輯

import shutil
  • copy():複製文件
  • copy2():複製文件,保留元數據
  • copyfileobj() 將一個文件的內容拷貝的另外一個文件當中
  • copyfile():將一個文件的內容拷貝的另外一個文件當中
  • copytree():複製整個文件目錄
  • copymode():拷貝權限
  • copystat():拷貝元數據(狀態)
  • rmtree():移除整個目錄,無論是否空
  • move():移動文件或者文件夾
  • which():檢測命令對應的文件路徑 注意:window和linux不太一樣。 window的命令都是.exe結尾,linux則不是
  • disk_usage():檢測磁盤使用信息
  • make_archive():歸檔函數,歸檔操作
  • unpack_archive():解包操作
  • get_archive_formats():獲取當前系統已註冊的歸檔文件格式(後綴)
  • get_unpack_formats():獲取當前系統已經註冊的解包文件格式(後綴)

glob模塊 編輯

glob模塊是最簡單的模塊之一,用通配符查找文件、路徑名。三個匹配符是「*」、「?」、「[」,其中「[]」匹配指定範圍內的字符。

  • glob.glob 返回所有匹配的文件、路徑列表。如果參數recursive=True, 模式「**」匹配任何文件或任何數目的子目錄組成的路徑;如果pattern以os.sep或os.altsep結尾,則不會匹配文件。「.」開始的文件、子目錄是隱藏的,默認不會被匹配,除非明確在模式中指明以「.」開始。
  • glob.iglob 返回匹配的文件、路徑的迭代器。
  • glob.escape(pathname):返回的字符串,把「*」、「?」、「[」字符用「[]」包圍起來。