跳至內容

Python/Standard Library

本頁使用了標題或全文手工轉換
維基教科書,自由的教學讀本

os模組

[編輯]

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() 啟動一個新行程; 进程=>zh-mo:行程
  • os.fork() 取得父行程; 进程=>zh-mo:行程ID,在子行程; 进程=>zh-mo:行程返回中返回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) 用來設定當前預設的字元編碼(詳細使用參考文件; 文档=>zh-mo:文件)
  • sys.displayhook(value) 如果value非空,這個函數會把他輸出到sys.stdout(詳細使用參考文件; 文档=>zh-mo:文件)
  • 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數,使用提前使用的格里高利曆法(proleptic Gregorian calendar)

實例方法和實例屬性:

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():Python 3.8 及以下返回格式如(year,week,weekday)的三元组;Python 3.9 及以上:返回一个具名三元对象 datetime.IsoCalendarDate,可通过属性访问:iso.year、iso.week、iso.weekday。
d1.isoformat():返回格式如'YYYY-MM-DD’的字符串;date.__str__()等效于该函数
d1.strftime(fmt):和time模块format相同。 date.__format__(format)等效于该函数
d1.toordinal():返回整型表示的从公元1年1月1日开始的day数,使用提前使用的格里高利历法(proleptic Gregorian calendar)
d1.ctime():等价于time.ctime(time.mktime(d.timetuple()))。如'Wed Dec  4 00:00:00 2002'

time類

[編輯]

建構函式或者返回time類物件:

datetime.time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0)
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:时区信息;
fold → 0 或 1(DST 折叠标志,Python 3.6+)

實例方法:

t1.replace([ hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ] ):创建一个新的时间对象,用参数指定的时、分、秒、微秒代替原有对象中的属性(原有对象仍保持不变);
t1.isoformat():返回型如"HH:MM:SS"格式的字符串表示;
t1.strftime(fmt):同time模块中的format;
utcoffset() → 返回 tzinfo.utcoffset(None)(如果有 tzinfo)
dst() → 返回 tzinfo.dst(None)
tzname() → 返回 tzinfo.tzname(None)

類屬性(常數):

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

支援操作

比较:< <= == != > >=(按时间顺序)
hash:可作为 dict 键(如果 tzinfo 为 None 或 hashable)

datetime類

[編輯]

datetime相當於date和time結合起來。是一個不可變(immutable)物件。

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

靜態方法和欄位

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

唯讀屬性

dt.year、month、day、hour、minute、second、microsecond、tzinfo: tzinfo为时区对象(值None表示naive时区)

方法

dt.date():获取date对象;
dt.time():获取time对象;
dt.timetz() 返回带时区 time 对象
dt.weekday():星期一为0
dt.isoweekday():星期一为1
dt.isocalendar():返回结果是三元组(年份,第几周,第几天)
dt.astimezone(tz=None):返回一个新的实例,其时区已经改变。如果参数为空,则使用本地时区。如果对象的tzinfo成员为空,实参为非本地时区,则从本地时区转换到实参指定的时区。如果tzinfo成员不为空,则改用实参指定的时区。
dt.replace ([ year=None , month=None , day=None , hour=None , minute=None , second=None , microsecond=None , tzinfo=None):返回一个新的实例,替换各个数据成员。例如保持原值不变,可以强行替换时区。
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.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,采取了proleptic Gregorian(提前使用的格里高利历法前推日期)
 *  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 位元組快取雜湊; 哈希=>zh-mo:雜湊
  • 1 位元組「hastzinfo」標誌
  • 10 位元組手動打包 unsigned char[10] 包含日期時間資料
  • 1 位元組「摺疊」標誌 ( DST-related )
  • 4 位元組填充,對齊 tzinfo 指標
  • 8 位元組 tzinfo 指標


timedelta類

[編輯]

表示兩個時間點的差值或一個持續時間(可正可負),支援加減運算、比較與縮放。內部為三元組(days、seconds、microseconds)表示。

使用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

類屬性

timedelta.min → -999_999_999 days + ...
timedelta.max → 999_999_999 days + ...
timedelta.resolution → timedelta(microseconds=1)

建構函式

timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)

實例屬性(唯讀)

days 表示总天数部分,可为负。归一化后承载了正负符号(负持续时间的符号通常体现在 days 上)。
seconds 取值范围始终归一化为 0 <= seconds < 86400(一天内的秒数),不携带正负符号。
microseconds 取值范围归一化为 0 <= microseconds < 1_000_000,不携带正负符号。

方法

total_seconds() → 浮点总秒数

支援操作

加减 timedelta 
乘除 int/float
取负、绝对值
比较

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的子類。

類屬性

timezone.utc → UTC 时区(偏移 0) # 获取UTC时区实例
timezone.min —— 最小合法时区偏移 (-timedelta(hours=24))
timezone.max —— 最大合法时区偏移

建構函式

timezone(offset, name=None)
# offset 为 timedelta
datetime.timezone(datetime.timedelta(hours=8), name="Asina/Shanghai")

實例方法

utcoffset(dt) → 返回 offset. 参数的的设计初衷是兼容 “可变偏移的时区”(如支持夏令时的时区),这类时区的偏移量高度依赖具体的时间点(dt)。因为 datetime.timezone 是专门用于表示固定偏移时区的类,它的偏移量从创建时就被固定,与具体的时间点(dt)无关。
tzname(dt) → 返回 name 或 "UTC±HH:MM" 若构造时未指定name,则返回偏移量的标准化字符串(如UTC+08:00)。参数dt无实际作用(因timezone不支持夏令时)。
dst(dt) → 返回 timedelta(0)   固定返回None,因为它仅支持固定偏移时区,不处理夏令时(若需支持夏令时,需自定义tzinfo子类)。若需支持夏令时,需自定义tzinfo子类
fromutc(dt) → 接收一个已绑定 UTC 时区的datetime对象,返回转换为当前时区的datetime对象(等价于dt.astimezone(self))

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) 更新雜湊; 哈希=>zh-mo:雜湊物件以字串參數, 注意:如果同一個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內建的標準模組,主要用於輸出執行紀錄檔,可以設定輸出紀錄檔的等級、紀錄檔儲存; 保存=>zh-mo:儲存路徑、紀錄檔檔案回滾等;相比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='%')
用於把一條紀錄檔的字典中的資訊,格式化輸出為文字; 文本=>zh-mo:文字。
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:列印行程; 进程=>zh-mo:行程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;紀錄檔輸出到記憶體; 内存=>zh-mo:記憶體中的指定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:特別糟糕的事情,如記憶體; 内存=>zh-mo:記憶體耗盡、磁碟空間為空,一般很少使用
  • ERROR:發生錯誤時,如IO操作失敗或者連接問題
  • WARNING:發生很重要的事件,但是並不是錯誤時,如用戶登錄密碼錯誤
  • INFO:處理請求或者狀態變化等日常事務
  • DEBUG:除錯過程中使用DEBUG等級,如演算法中每個迴圈的中間狀態

擷取; 捕获=>zh-mo:擷取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',並對它進行了組態,就可以在直譯器行程; 进程=>zh-mo:行程裏面的其他地方通過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中新增的一個模組,它允許生成新的行程; 进程=>zh-mo:行程,連接到它們的 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之後的版本中,官方文件; 文档=>zh-mo:文件中提倡通過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,且執行命令的行程; 进程=>zh-mo:行程以非0狀態碼退出,則會投擲一個CalledProcessError的異常,且該異常物件會包含 參數、退出狀態碼、以及stdout和stderr(如果它們有被擷取; 捕获=>zh-mo:擷取的話)。

stdout, stderr:

  • run()函數預設不會擷取; 捕获=>zh-mo:擷取命令執行結果的正常輸出和錯誤輸出,如果我們向取得這些內容需要傳遞subprocess.PIPE,然後可以通過返回的CompletedProcess類別實例的stdout和stderr屬性或擷取; 捕获=>zh-mo:擷取相應的內容;
  • call()和check_call()函數返回的是命令執行的狀態碼,而不是CompletedProcess類別實例,所以對於它們而言,stdout和stderr不適合賦值為subprocess.PIPE;
  • check_output()函數預設就會返回命令執行結果,所以不用設定stdout的值,如果我們希望在結果中擷取; 捕获=>zh-mo:擷取錯誤資訊,可以執行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中才存在的。它表示的是一個已結束行程; 进程=>zh-mo:行程的狀態資訊,它所包含的屬性如下:

  • args: 用於載入該行程; 进程=>zh-mo:行程的參數,這可能是一個列表或一個字串
  • returncode: 子行程; 进程=>zh-mo:行程的退出狀態碼。通常情況下,退出狀態碼為0則表示行程; 进程=>zh-mo:行程成功執行了;一個負值-N表示這個子行程; 进程=>zh-mo:行程被訊號N終止了
  • stdout: 從子行程; 进程=>zh-mo:行程擷取; 捕获=>zh-mo:擷取的stdout。這通常是一個位元組序列,如果run()函數被呼叫時指定universal_newlines=True,則該屬性值是一個字串。如果run()函數被呼叫時指定stderr=subprocess.STDOUT,那麼stdout和stderr將會被整合到這一個屬性中,且stderr將會為None
  • stderr: 從子行程; 进程=>zh-mo:行程擷取; 捕获=>zh-mo:擷取的stderr。它的值與stdout一樣,是一個位元組序列或一個字串。如果stderr滅有被擷取; 捕获=>zh-mo:擷取的話,它的值就為None
  • check_returncode(): 如果returncode是一個非0值,則該方法會投擲一個CalledProcessError異常。

subprocess.Popen

[編輯]

該類用於在一個新的行程; 进程=>zh-mo:行程中執行一個子程式。前面我們提到過,上面介紹的這些函數都是基於subprocess.Popen類實現的,通過使用這些被封裝後的進階函數可以很方面的完成一些常見的需求。由於subprocess模組底層的行程; 进程=>zh-mo:行程建立和管理是由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: 用於指定一個將在子行程; 进程=>zh-mo:行程執行之前被呼叫的可執行物件,只在Unix平台下有效。
  • close_fds: 如果該參數的值為True,則除了0,1和2之外的所有檔案描述符都將會在子行程; 进程=>zh-mo:行程執行之前被關閉。
  • shell: 該參數用於標識是否使用shell作為要執行的程式,如果shell值為True,則建議將args參數作為一個字串傳遞而不要作為一個序列傳遞。
  • cwd: 如果該參數值不是None,則該函數將會在執行這個子行程; 进程=>zh-mo:行程之前改變當前工作目錄。
  • env: 用於指定子行程; 进程=>zh-mo:行程的環境變數,如果env=None,那麼子行程; 进程=>zh-mo:行程的環境變數將從父行程; 进程=>zh-mo:行程中繼承。如果env!=None,它的值必須是一個對映物件。
  • universal_newlines: 如果該參數值為True,則該檔案物件的stdin,stdout和stderr將會作為文字; 文本=>zh-mo:文字流被打開,否則他們將會被作為二進制流被打開。
  • startupinfo和creationflags: 這兩個參數只在Windows下有效,它們將被傳遞給底層的CreateProcess()函數,用於設定子行程; 进程=>zh-mo:行程的一些屬性,如主窗口的外觀,行程; 进程=>zh-mo:行程優先級等。

subprocess.Popen類別的實例可呼叫的方法

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

關於communicate()方法的說明:

  • 該方法中的可選參數 input 應該是將被傳送給子行程; 进程=>zh-mo:行程的資料,或者如沒有資料傳送給子行程; 进程=>zh-mo:行程,該參數應該是None。input參數的資料類型必須是位元組串,如果universal_newlines參數值為True,則input參數的資料類型必須是字串。
  • 該方法返回一個元組(stdout_data, stderr_data),這些資料將會是位元組穿或字串(如果universal_newlines的值為True)。
  • 如果在timeout指定的秒數後該行程; 进程=>zh-mo:行程還沒有結束,將會投擲一個TimeoutExpired異常。擷取; 捕获=>zh-mo:擷取這個異常,然後重新嘗試通信不會遺失任何輸出的資料。但是逾時之後子行程; 进程=>zh-mo:行程並沒有被殺死,為了合理的清除相應的內容,一個好的應用應該手動殺死這個子行程; 进程=>zh-mo:行程來結束通信。
  • 需要注意的是,這裏讀取的資料是緩衝在記憶體; 内存=>zh-mo:記憶體中的,所以,如果資料大小非常大或者是無限的,就不應該使用這個方法。

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儲存; 保存=>zh-mo:儲存到檔案中
  • 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):返回的字串,把「*」、「?」、「[」字元用「[]」包圍起來。